无法在 XSLT 中调用扩展函数
Unable to invoke extension function in XSLT
我们的项目是用 Spring Boot 编写的,我们正在 Spring Boot 中集成 Apache Camel。在我们的 Camel 路由中,我们从源系统接收 XML,在 XSLT 中转换它并将 XML 输出发送到目标系统。在 XSLT 中,我们使用扩展函数:
xmlns:exsl="http://exslt.org/common"
我们正在 JBoss EAP 中将项目部署为 war 文件。问题是扩展函数在调用时抛出以下异常:
javax.xml.transform.TransformerException: Extension function: '{http://exslt.org/common}node-set' can not be invoked when the XMLConstants.FEATURE_SECURE_PROCESSING feature is set to true.
at org.apache.xpath.functions.FuncExtFunction.execute(FuncExtFunction.java:186)
at org.apache.xpath.axes.FilterExprIteratorSimple.executeFilterExpr(FilterExprIteratorSimple.java:116)
at org.apache.xpath.axes.FilterExprWalker.setRoot(FilterExprWalker.java:131)
at org.apache.xpath.axes.WalkingIterator.setRoot(WalkingIterator.java:157)
at org.apache.xpath.axes.NodeSequence.setRoot(NodeSequence.java:265)
at org.apache.xpath.axes.LocPathIterator.asIterator(LocPathIterator.java:269)
at org.apache.xalan.templates.ElemForEach.transformSelectedNodes(ElemForEach.java:335)
at org.apache.xalan.templates.ElemForEach.execute(ElemForEach.java:265)
at org.apache.xalan.transformer.TransformerImpl.executeChildTemplates(TransformerImpl.java:2402)
at org.apache.xalan.templates.ElemIf.execute(ElemIf.java:162)
at org.apache.xalan.templates.ElemForEach.transformSelectedNodes(ElemForEach.java:425)
at org.apache.xalan.templates.ElemForEach.execute(ElemForEach.java:265)
at org.apache.xalan.transformer.TransformerImpl.executeChildTemplates(TransformerImpl.java:2402)
at org.apache.xalan.templates.ElemLiteralResult.execute(ElemLiteralResult.java:1376)
at org.apache.xalan.transformer.TransformerImpl.executeChildTemplates(TransformerImpl.java:2402)
at org.apache.xalan.templates.ElemLiteralResult.execute(ElemLiteralResult.java:1376)
at org.apache.xalan.transformer.TransformerImpl.executeChildTemplates(TransformerImpl.java:2402)
at org.apache.xalan.templates.ElemLiteralResult.execute(ElemLiteralResult.java:1376)
at org.apache.xalan.templates.ElemApplyTemplates.transformSelectedNodes(ElemApplyTemplates.java:395)
at org.apache.xalan.templates.ElemApplyTemplates.execute(ElemApplyTemplates.java:178)
at org.apache.xalan.transformer.TransformerImpl.executeChildTemplates(TransformerImpl.java:2402)
at org.apache.xalan.transformer.TransformerImpl.applyTemplateToNode(TransformerImpl.java:2272)
at org.apache.xalan.transformer.TransformerImpl.transformNode(TransformerImpl.java:1358)
at org.apache.xalan.transformer.TransformerImpl.transform(TransformerImpl.java:711)
at org.apache.xalan.transformer.TransformerImpl.transform(TransformerImpl.java:1275)
at org.apache.xalan.transformer.TransformerImpl.transform(TransformerImpl.java:1253)
at org.apache.camel.builder.xml.XsltBuilder.process(XsltBuilder.java:142)
at org.apache.camel.impl.ProcessorEndpoint.onExchange(ProcessorEndpoint.java:103)
at org.apache.camel.component.xslt.XsltEndpoint.onExchange(XsltEndpoint.java:149)
at org.apache.camel.impl.ProcessorEndpoint.process(ProcessorEndpoint.java:71)
at org.apache.camel.util.AsyncProcessorConverterHelper$ProcessorToAsyncProcessorBridge.process(AsyncProcessorConverterHelper.java:61)
at org.apache.camel.processor.SendProcessor.process(SendProcessor.java:148)
at org.apache.camel.processor.RedeliveryErrorHandler.process(RedeliveryErrorHandler.java:548)
at org.apache.camel.processor.CamelInternalProcessor.process(CamelInternalProcessor.java:201)
at org.apache.camel.processor.ChoiceProcessor.process(ChoiceProcessor.java:117)
at org.apache.camel.processor.RedeliveryErrorHandler.process(RedeliveryErrorHandler.java:548)
at org.apache.camel.processor.CamelInternalProcessor.process(CamelInternalProcessor.java:201)
at org.apache.camel.processor.Pipeline.process(Pipeline.java:138)
at org.apache.camel.processor.Pipeline.process(Pipeline.java:101)
at org.apache.camel.processor.CamelInternalProcessor.process(CamelInternalProcessor.java:201)
at org.apache.camel.component.direct.DirectProducer.process(DirectProducer.java:76)
at org.apache.camel.processor.SendProcessor.process(SendProcessor.java:148)
at org.apache.camel.processor.RedeliveryErrorHandler.process(RedeliveryErrorHandler.java:548)
at org.apache.camel.processor.CamelInternalProcessor.process(CamelInternalProcessor.java:201)
at org.apache.camel.processor.Pipeline.process(Pipeline.java:138)
at org.apache.camel.processor.Pipeline.process(Pipeline.java:101)
at org.apache.camel.processor.CamelInternalProcessor.process(CamelInternalProcessor.java:201)
at org.apache.camel.component.direct.DirectProducer.process(DirectProducer.java:76)
at org.apache.camel.processor.SendProcessor.process(SendProcessor.java:148)
at org.apache.camel.processor.RedeliveryErrorHandler.process(RedeliveryErrorHandler.java:548)
at org.apache.camel.processor.CamelInternalProcessor.process(CamelInternalProcessor.java:201)
at org.apache.camel.processor.Pipeline.process(Pipeline.java:138)
at org.apache.camel.processor.Pipeline.process(Pipeline.java:101)
at org.apache.camel.processor.ChoiceProcessor.process(ChoiceProcessor.java:117)
at org.apache.camel.processor.RedeliveryErrorHandler.process(RedeliveryErrorHandler.java:548)
at org.apache.camel.processor.CamelInternalProcessor.process(CamelInternalProcessor.java:201)
at org.apache.camel.processor.ChoiceProcessor.process(ChoiceProcessor.java:117)
at org.apache.camel.processor.RedeliveryErrorHandler.process(RedeliveryErrorHandler.java:548)
at org.apache.camel.processor.CamelInternalProcessor.process(CamelInternalProcessor.java:201)
at org.apache.camel.processor.Pipeline.process(Pipeline.java:138)
at org.apache.camel.processor.Pipeline.process(Pipeline.java:101)
at org.apache.camel.processor.ChoiceProcessor.process(ChoiceProcessor.java:117)
at org.apache.camel.processor.RedeliveryErrorHandler.process(RedeliveryErrorHandler.java:548)
at org.apache.camel.processor.CamelInternalProcessor.process(CamelInternalProcessor.java:201)
at org.apache.camel.processor.Pipeline.process(Pipeline.java:138)
at org.apache.camel.processor.Pipeline.process(Pipeline.java:101)
at org.apache.camel.processor.CamelInternalProcessor.process(CamelInternalProcessor.java:201)
at org.apache.camel.processor.DelegateAsyncProcessor.process(DelegateAsyncProcessor.java:97)
at org.apache.camel.component.jms.EndpointMessageListener.onMessage(EndpointMessageListener.java:113)
at org.springframework.jms.listener.AbstractMessageListenerContainer.doInvokeListener(AbstractMessageListenerContainer.java:736)
at org.springframework.jms.listener.AbstractMessageListenerContainer.invokeListener(AbstractMessageListenerContainer.java:696)
at org.springframework.jms.listener.AbstractMessageListenerContainer.doExecuteListener(AbstractMessageListenerContainer.java:674)
at org.springframework.jms.listener.AbstractPollingMessageListenerContainer.doReceiveAndExecute(AbstractPollingMessageListenerContainer.java:318)
at org.springframework.jms.listener.AbstractPollingMessageListenerContainer.receiveAndExecute(AbstractPollingMessageListenerContainer.java:257)
at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.invokeListener(DefaultMessageListenerContainer.java:1189)
at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.executeOngoingLoop(DefaultMessageListenerContainer.java:1179)
at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.run(DefaultMessageListenerContainer.java:1076)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
我们使用的software版本如下:
Spring 启动 - 2.3.3.RELEASE
阿帕奇骆驼:2.25 1
XSLT:1.0
JBoss EAP:7.3.0
请建议如何解决此问题。
我说异常说明了一切
您需要像这样创建自己 class:
public final class XmlUtil {
private static final Logger log = LoggerFactory.getLogger("XmlUtilLOG");
protected XmlUtil() {
// empty on purpose to avoid instatiation
}
private static class InstanceHolder {
public static final XmlUtil INSTANCE = new XmlUtil();
private InstanceHolder() {
// only to hold instance
}
}
private final ThreadLocal<TransformerFactory> transformerFactory = new ThreadLocal<TransformerFactory>() {
@Override
protected TransformerFactory initialValue() {
TransformerFactory tf;
try {
tf = TransformerFactory.newInstance("net.sf.saxon.TransformerFactoryImpl",
XmlHelper.class.getClassLoader());
} catch (TransformerFactoryConfigurationError e) {
logger.error("", e);
tf = TransformerFactory.newInstance();
}
try {
tf.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, false);
} catch (TransformerConfigurationException e) {
logger.error("transformer factory feature {} not supported: {}",
XMLConstants.FEATURE_SECURE_PROCESSING,
e.getMessage());
}
return tf;
}
};
private final ThreadLocal<DocumentBuilder> documentBuilder = ThreadLocal.withInitial(() -> {
try {
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
documentBuilderFactory.setIgnoringComments(true);
documentBuilderFactory.setIgnoringElementContentWhitespace(true);
documentBuilderFactory.setNamespaceAware(true);
documentBuilderFactory.setFeature(
XMLConstants.FEATURE_SECURE_PROCESSING, false);
documentBuilderFactory.setFeature(
"http://apache.org/xml/features/disallow-doctype-decl", true);
return documentBuilderFactory.newDocumentBuilder();
} catch (ParserConfigurationException e) {
logger.error("Error on XML Document builder intialization", e);
throw new XmlConfigurationException(e);
}
});
public XmlUtil getInstance() {
return InstanceHolder.INSTANCE;
}
public Document transform(Node source, InputStream xsltStream) throws TransformerException, XmlParseException {
Document outputDocument = newDocument();
Document inputDocument;
if (source instanceof Document) {
inputDocument = (Document) source;
} else {
inputDocument = newDocument();
Node sourceImported = inputDocument.importNode(source, true);
inputDocument.appendChild(sourceImported);
}
Transformer xslt = getTransformerFactory().newTransformer(new StreamSource(xsltStream));
DOMSource domSource = new DOMSource(inputDocument);
DOMResult domResult = new DOMResult(outputDocument);
xslt.transform(domSource, domResult);
if (logger.isDebugEnabled()) {
logger.debug(xslt.getClass().getName());
logger.debug("XSLT RESULT: [{}]", serialize(outputDocument));
}
return outputDocument;
}
public Document newDocument() {
return getDocumentBuilder().newDocument();
}
private TransformerFactory getTransformerFactory() {
return this.transformerFactory.get();
}
private DocumentBuilder getDocumentBuilder() {
return this.documentBuilder.get();
}
}
但是我无法实际测试它,因为我没有您正在使用的 spring 应用程序,所以您需要自己尝试一下
我们的项目是用 Spring Boot 编写的,我们正在 Spring Boot 中集成 Apache Camel。在我们的 Camel 路由中,我们从源系统接收 XML,在 XSLT 中转换它并将 XML 输出发送到目标系统。在 XSLT 中,我们使用扩展函数:
xmlns:exsl="http://exslt.org/common"
我们正在 JBoss EAP 中将项目部署为 war 文件。问题是扩展函数在调用时抛出以下异常:
javax.xml.transform.TransformerException: Extension function: '{http://exslt.org/common}node-set' can not be invoked when the XMLConstants.FEATURE_SECURE_PROCESSING feature is set to true.
at org.apache.xpath.functions.FuncExtFunction.execute(FuncExtFunction.java:186)
at org.apache.xpath.axes.FilterExprIteratorSimple.executeFilterExpr(FilterExprIteratorSimple.java:116)
at org.apache.xpath.axes.FilterExprWalker.setRoot(FilterExprWalker.java:131)
at org.apache.xpath.axes.WalkingIterator.setRoot(WalkingIterator.java:157)
at org.apache.xpath.axes.NodeSequence.setRoot(NodeSequence.java:265)
at org.apache.xpath.axes.LocPathIterator.asIterator(LocPathIterator.java:269)
at org.apache.xalan.templates.ElemForEach.transformSelectedNodes(ElemForEach.java:335)
at org.apache.xalan.templates.ElemForEach.execute(ElemForEach.java:265)
at org.apache.xalan.transformer.TransformerImpl.executeChildTemplates(TransformerImpl.java:2402)
at org.apache.xalan.templates.ElemIf.execute(ElemIf.java:162)
at org.apache.xalan.templates.ElemForEach.transformSelectedNodes(ElemForEach.java:425)
at org.apache.xalan.templates.ElemForEach.execute(ElemForEach.java:265)
at org.apache.xalan.transformer.TransformerImpl.executeChildTemplates(TransformerImpl.java:2402)
at org.apache.xalan.templates.ElemLiteralResult.execute(ElemLiteralResult.java:1376)
at org.apache.xalan.transformer.TransformerImpl.executeChildTemplates(TransformerImpl.java:2402)
at org.apache.xalan.templates.ElemLiteralResult.execute(ElemLiteralResult.java:1376)
at org.apache.xalan.transformer.TransformerImpl.executeChildTemplates(TransformerImpl.java:2402)
at org.apache.xalan.templates.ElemLiteralResult.execute(ElemLiteralResult.java:1376)
at org.apache.xalan.templates.ElemApplyTemplates.transformSelectedNodes(ElemApplyTemplates.java:395)
at org.apache.xalan.templates.ElemApplyTemplates.execute(ElemApplyTemplates.java:178)
at org.apache.xalan.transformer.TransformerImpl.executeChildTemplates(TransformerImpl.java:2402)
at org.apache.xalan.transformer.TransformerImpl.applyTemplateToNode(TransformerImpl.java:2272)
at org.apache.xalan.transformer.TransformerImpl.transformNode(TransformerImpl.java:1358)
at org.apache.xalan.transformer.TransformerImpl.transform(TransformerImpl.java:711)
at org.apache.xalan.transformer.TransformerImpl.transform(TransformerImpl.java:1275)
at org.apache.xalan.transformer.TransformerImpl.transform(TransformerImpl.java:1253)
at org.apache.camel.builder.xml.XsltBuilder.process(XsltBuilder.java:142)
at org.apache.camel.impl.ProcessorEndpoint.onExchange(ProcessorEndpoint.java:103)
at org.apache.camel.component.xslt.XsltEndpoint.onExchange(XsltEndpoint.java:149)
at org.apache.camel.impl.ProcessorEndpoint.process(ProcessorEndpoint.java:71)
at org.apache.camel.util.AsyncProcessorConverterHelper$ProcessorToAsyncProcessorBridge.process(AsyncProcessorConverterHelper.java:61)
at org.apache.camel.processor.SendProcessor.process(SendProcessor.java:148)
at org.apache.camel.processor.RedeliveryErrorHandler.process(RedeliveryErrorHandler.java:548)
at org.apache.camel.processor.CamelInternalProcessor.process(CamelInternalProcessor.java:201)
at org.apache.camel.processor.ChoiceProcessor.process(ChoiceProcessor.java:117)
at org.apache.camel.processor.RedeliveryErrorHandler.process(RedeliveryErrorHandler.java:548)
at org.apache.camel.processor.CamelInternalProcessor.process(CamelInternalProcessor.java:201)
at org.apache.camel.processor.Pipeline.process(Pipeline.java:138)
at org.apache.camel.processor.Pipeline.process(Pipeline.java:101)
at org.apache.camel.processor.CamelInternalProcessor.process(CamelInternalProcessor.java:201)
at org.apache.camel.component.direct.DirectProducer.process(DirectProducer.java:76)
at org.apache.camel.processor.SendProcessor.process(SendProcessor.java:148)
at org.apache.camel.processor.RedeliveryErrorHandler.process(RedeliveryErrorHandler.java:548)
at org.apache.camel.processor.CamelInternalProcessor.process(CamelInternalProcessor.java:201)
at org.apache.camel.processor.Pipeline.process(Pipeline.java:138)
at org.apache.camel.processor.Pipeline.process(Pipeline.java:101)
at org.apache.camel.processor.CamelInternalProcessor.process(CamelInternalProcessor.java:201)
at org.apache.camel.component.direct.DirectProducer.process(DirectProducer.java:76)
at org.apache.camel.processor.SendProcessor.process(SendProcessor.java:148)
at org.apache.camel.processor.RedeliveryErrorHandler.process(RedeliveryErrorHandler.java:548)
at org.apache.camel.processor.CamelInternalProcessor.process(CamelInternalProcessor.java:201)
at org.apache.camel.processor.Pipeline.process(Pipeline.java:138)
at org.apache.camel.processor.Pipeline.process(Pipeline.java:101)
at org.apache.camel.processor.ChoiceProcessor.process(ChoiceProcessor.java:117)
at org.apache.camel.processor.RedeliveryErrorHandler.process(RedeliveryErrorHandler.java:548)
at org.apache.camel.processor.CamelInternalProcessor.process(CamelInternalProcessor.java:201)
at org.apache.camel.processor.ChoiceProcessor.process(ChoiceProcessor.java:117)
at org.apache.camel.processor.RedeliveryErrorHandler.process(RedeliveryErrorHandler.java:548)
at org.apache.camel.processor.CamelInternalProcessor.process(CamelInternalProcessor.java:201)
at org.apache.camel.processor.Pipeline.process(Pipeline.java:138)
at org.apache.camel.processor.Pipeline.process(Pipeline.java:101)
at org.apache.camel.processor.ChoiceProcessor.process(ChoiceProcessor.java:117)
at org.apache.camel.processor.RedeliveryErrorHandler.process(RedeliveryErrorHandler.java:548)
at org.apache.camel.processor.CamelInternalProcessor.process(CamelInternalProcessor.java:201)
at org.apache.camel.processor.Pipeline.process(Pipeline.java:138)
at org.apache.camel.processor.Pipeline.process(Pipeline.java:101)
at org.apache.camel.processor.CamelInternalProcessor.process(CamelInternalProcessor.java:201)
at org.apache.camel.processor.DelegateAsyncProcessor.process(DelegateAsyncProcessor.java:97)
at org.apache.camel.component.jms.EndpointMessageListener.onMessage(EndpointMessageListener.java:113)
at org.springframework.jms.listener.AbstractMessageListenerContainer.doInvokeListener(AbstractMessageListenerContainer.java:736)
at org.springframework.jms.listener.AbstractMessageListenerContainer.invokeListener(AbstractMessageListenerContainer.java:696)
at org.springframework.jms.listener.AbstractMessageListenerContainer.doExecuteListener(AbstractMessageListenerContainer.java:674)
at org.springframework.jms.listener.AbstractPollingMessageListenerContainer.doReceiveAndExecute(AbstractPollingMessageListenerContainer.java:318)
at org.springframework.jms.listener.AbstractPollingMessageListenerContainer.receiveAndExecute(AbstractPollingMessageListenerContainer.java:257)
at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.invokeListener(DefaultMessageListenerContainer.java:1189)
at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.executeOngoingLoop(DefaultMessageListenerContainer.java:1179)
at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.run(DefaultMessageListenerContainer.java:1076)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
我们使用的software版本如下:
Spring 启动 - 2.3.3.RELEASE 阿帕奇骆驼:2.25 1 XSLT:1.0 JBoss EAP:7.3.0
请建议如何解决此问题。
我说异常说明了一切
您需要像这样创建自己 class:
public final class XmlUtil {
private static final Logger log = LoggerFactory.getLogger("XmlUtilLOG");
protected XmlUtil() {
// empty on purpose to avoid instatiation
}
private static class InstanceHolder {
public static final XmlUtil INSTANCE = new XmlUtil();
private InstanceHolder() {
// only to hold instance
}
}
private final ThreadLocal<TransformerFactory> transformerFactory = new ThreadLocal<TransformerFactory>() {
@Override
protected TransformerFactory initialValue() {
TransformerFactory tf;
try {
tf = TransformerFactory.newInstance("net.sf.saxon.TransformerFactoryImpl",
XmlHelper.class.getClassLoader());
} catch (TransformerFactoryConfigurationError e) {
logger.error("", e);
tf = TransformerFactory.newInstance();
}
try {
tf.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, false);
} catch (TransformerConfigurationException e) {
logger.error("transformer factory feature {} not supported: {}",
XMLConstants.FEATURE_SECURE_PROCESSING,
e.getMessage());
}
return tf;
}
};
private final ThreadLocal<DocumentBuilder> documentBuilder = ThreadLocal.withInitial(() -> {
try {
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
documentBuilderFactory.setIgnoringComments(true);
documentBuilderFactory.setIgnoringElementContentWhitespace(true);
documentBuilderFactory.setNamespaceAware(true);
documentBuilderFactory.setFeature(
XMLConstants.FEATURE_SECURE_PROCESSING, false);
documentBuilderFactory.setFeature(
"http://apache.org/xml/features/disallow-doctype-decl", true);
return documentBuilderFactory.newDocumentBuilder();
} catch (ParserConfigurationException e) {
logger.error("Error on XML Document builder intialization", e);
throw new XmlConfigurationException(e);
}
});
public XmlUtil getInstance() {
return InstanceHolder.INSTANCE;
}
public Document transform(Node source, InputStream xsltStream) throws TransformerException, XmlParseException {
Document outputDocument = newDocument();
Document inputDocument;
if (source instanceof Document) {
inputDocument = (Document) source;
} else {
inputDocument = newDocument();
Node sourceImported = inputDocument.importNode(source, true);
inputDocument.appendChild(sourceImported);
}
Transformer xslt = getTransformerFactory().newTransformer(new StreamSource(xsltStream));
DOMSource domSource = new DOMSource(inputDocument);
DOMResult domResult = new DOMResult(outputDocument);
xslt.transform(domSource, domResult);
if (logger.isDebugEnabled()) {
logger.debug(xslt.getClass().getName());
logger.debug("XSLT RESULT: [{}]", serialize(outputDocument));
}
return outputDocument;
}
public Document newDocument() {
return getDocumentBuilder().newDocument();
}
private TransformerFactory getTransformerFactory() {
return this.transformerFactory.get();
}
private DocumentBuilder getDocumentBuilder() {
return this.documentBuilder.get();
}
}
但是我无法实际测试它,因为我没有您正在使用的 spring 应用程序,所以您需要自己尝试一下