Как связать XMLReader, осведомленный о XInclude, с XMLFilter, чтобы включение XInclude выполнялось для любых элементов, которые изменил фильтр?

В Java синтаксический анализ XML - объединение выходных данных xi:include автор хотел использовать XInclude, но использовал неправильное пространство имен на include элемент. Я подумал, что XMLFilter, поставленный перед синтаксическим анализатором XInclude, где XMLFilter заботится о корректировке пространства имен, может решить эту проблему (без необходимости редактировать файлы вручную, соответственно, без отдельного шага обработки, который сначала создает промежуточные файлы с исправленным пространством имен),

Поэтому я написал следующее XMLFilter, расширяя XMLFilterImpl что SAX обеспечивает:

import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.XMLFilterImpl;


public class XIncludeNsFixup extends XMLFilterImpl {

    static String correctURI = "http://www.w3.org/2001/XInclude";
    static String oldURI = "http://www.w3.org/2003/XInclude";

    @Override
    public void startElement(String uri, String localName, String qName, Attributes atts) throws SAXException {
        if (uri.equals(oldURI)) {
            super.startElement(correctURI, localName, qName, atts);
        }
        else {
            super.startElement(uri, localName, qName, atts);
        }
    }

    @Override
    public void endElement(String uri, String localName, String qName) throws SAXException {
        if (uri.equals(oldURI)) {
            super.endElement(correctURI, localName, qName);
        }
        else {
            super.endElement(uri, localName, qName);
        }
    }

    @Override
    public void startPrefixMapping(String prefix, String uri) throws SAXException {
        if (uri.equals(oldURI)) {
            super.startPrefixMapping(prefix, correctURI);
        }
        else {
            super.startPrefixMapping(prefix, uri);
        }
    }

}

Затем я создал XInclude SAXParser соответственно XMLReader быть прикованным к этому фильтру и загрузить образец документа в виде SAXSource из этого фильтра в дефолт Transformer построить DOMResult:

    SAXParserFactory spf = SAXParserFactory.newInstance();
    spf.setNamespaceAware(true);
    spf.setXIncludeAware(true);

    XMLReader inputReader = spf.newSAXParser().getXMLReader();

    XMLFilter fixNs = new XIncludeNsFixup();
    fixNs.setParent(inputReader);

    TransformerFactory tf = TransformerFactory.newInstance();

    Transformer builder = tf.newTransformer();

    DOMResult fixedInput = new DOMResult();

    builder.transform(new SAXSource(fixNs, new InputSource("file3.xml")), fixedInput);

    Document doc = (Document) fixedInput.getNode();

    Transformer serializer = tf.newTransformer();

    serializer.transform(new DOMSource(doc), new StreamResult(System.out));

Образец документа file3.xml что я использовал есть один xi:xinclude элемент в правильном пространстве имен XInclude и один в старом, не поддерживаемом пространстве имен:

<?xml version="1.0" encoding="UTF-8"?>
<contexts>
    <context name="a">
        <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="reuse.xml"/>
        <foo>Original text 1.</foo>
    </context>
    <context name="b">
        <xi:include xmlns:xi="http://www.w3.org/2003/XInclude" href="reuse.xml"/>
        <foo>Original text 2.</foo>
    </context>
</contexts>

Я ожидаю, что фильтр сначала исправляет пространство имен, а затем XMLReader выполняет XInclude для обоих элементов. Однако при запуске кода с Java 1.8 вывод выглядит следующим образом:

<?xml version="1.0" encoding="UTF-8" standalone="no"?><contexts>
    <context name="a">
        <text xml:base="reuse.xml">I am XIncluded text.</text>
        <foo>Original text 1.</foo>
    </context>
    <context name="b">
        <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="reuse.xml"/>
        <foo>Original text 2.</foo>
    </context>
</contexts>

Таким образом, фильтр зафиксировал пространство имен на втором include элемент, но XMLReader только применил включение XInclude на первом include элемент.

Где я ошибся? Как связать фильтр и XMLReader с поддержкой XInclude, чтобы исправить пространство имен и выполнить включение XInclude в исправленные элементы пространства имен?

Для полноты вот reuse.xml:

<?xml version="1.0" encoding="UTF-8"?>
<text>I am XIncluded text.</text>

И полный код Java-программы для легкого тестирования:

import java.io.IOException;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParserFactory;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMResult;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.sax.SAXSource;
import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.Document;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLFilter;
import org.xml.sax.XMLReader;


public class XIncludeTest1 {


    public static void main(String[] args) throws ParserConfigurationException, SAXException, IOException, TransformerConfigurationException, TransformerException {

        SAXParserFactory spf = SAXParserFactory.newInstance();
        spf.setNamespaceAware(true);
        spf.setXIncludeAware(true);

        XMLReader inputReader = spf.newSAXParser().getXMLReader();

        XMLFilter fixNs = new XIncludeNsFixup();
        fixNs.setParent(inputReader);

        TransformerFactory tf = TransformerFactory.newInstance();

        Transformer builder = tf.newTransformer();

        DOMResult fixedInput = new DOMResult();

        builder.transform(new SAXSource(fixNs, new InputSource("file3.xml")), fixedInput);

        Document doc = (Document) fixedInput.getNode();

        Transformer serializer = tf.newTransformer();

        serializer.transform(new DOMSource(doc), new StreamResult(System.out));
    }

}

Я также попытался поместить последнюю версию Xerces Java от Apache в путь к классам, чтобы увидеть, устраняет ли она проблему, но вывод остается прежним.

0 ответов

Другие вопросы по тегам