Не удается вызвать функцию расширения в XSLT

#spring-boot #apache-camel #xslt-1.0 #jboss-eap-7

Вопрос:

Наш проект написан в Spring Boot, и мы интегрируем Apache Camel в Spring Boot. В нашем верблюжьем маршруте мы получаем XML-файл из исходной системы, преобразуем его в XSLT и отправляем выходные данные XML в целевую систему. В XSLT мы используем функцию расширения:

 xmlns:exsl="http://exslt.org/common" 
 

Мы развертываем проект в виде файла war в JBoss EAP. Prblem заключается в том, что функция расширения создает исключение ниже, когда она вызывается:

 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$1.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)
 

Версии программного обеспечения, которые мы используем, следующие:

Весенняя загрузка — 2.3.3.ВЫПУСК Apache Camel: 2.25 1 XSLT: 1.0 JBoss EAP: 7.3.0

Пожалуйста, подскажите, как решить эту проблему.

Комментарии:

1. xmlns:exsl="http://exslt.org/common" это не функция расширения — это объявление пространства имен. Функция, похоже, есть exsl:node-set() — и я верю, что у вас есть довольно четкое сообщение относительно причины.

2. Как я могу установить XMLКонстанты. особенность. безопасный. ОБРАБОТКА в false?

3. И можете ли вы предположить, почему он установлен в значение true?

4. Боюсь, я не знаю ничего, кроме того, что уже сказал.

Ответ №1:

Я скажу, что это исключение говорит само за себя

Вам нужно создать себе такой класс, как этот:

 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, которое вы используете, поэтому вам нужно попробовать это самостоятельно