编程语言
首页 > 编程语言> > Java StAX解析器无法解析有效的xml

Java StAX解析器无法解析有效的xml

作者:互联网

家伙.

我花了很多时间试图了解这是一个错误还是我自己缺乏教育.基本上,我正在尝试对特定元素做出反应,并使用Java StAX API使用Transformer读取其内容.

当XML格式相当或元素之间有空格时,一切都有效.但是,只要它看到XML在元素之间没有空格字符,它就会严重破坏.

有代码及其输出来说明问题.

有3个示例XML,前2个显示2个不同的中断场景,而最后一个显示正确的处理:

>在没有空格的第一个场景中,它会跳过一些元素.在下面的示例中,它跳过除一个“node”元素之外的所有元素.在现实世界中,它会跳过其他每个节点.可能是因为节点内容更丰富.
>在第二种情况下,我仅在节点元素之间添加了空格.如您所见,它无法正确处理文档的结尾.
>在最后一个场景中,我在最后一个节点和关闭根元素之间添加了空格.处理按需要进行.

在我的真实世界场景中,我期望单行无分隔符XML,因此我需要方案1正常工作,并且也很高兴知道对XML的有效更改(例如在元素之间添加空格)不会破坏处理比如场景2.

请帮忙!!!

完整的单类应用程序测试代码.StAXTest:

package test;

import java.io.StringReader;
import java.io.StringWriter;

import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamConstants;
import javax.xml.stream.XMLStreamReader;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.stax.StAXSource;
import javax.xml.transform.stream.StreamResult;

public class StAXTest {
    private final static String XML1 = "<root><node></node><node></node></root>";
    private final static String XML2 = "<root><node></node> <node></node></root>";
    private final static String XML3 = "<root><node></node> <node></node> </root>";

    public static void main(String[] args) throws Exception {
        processXML(XML1);
        processXML(XML2);
        processXML(XML3);
    }

    private static void processXML(String xml) {
        try {
            System.out.println("XML Input:\n" + xml + "\nProcessing:");

            XMLInputFactory xif = XMLInputFactory.newInstance();
            XMLStreamReader reader = xif.createXMLStreamReader(new StringReader(xml));
            TransformerFactory tf = TransformerFactory.newInstance();

            int nodeCount = 0;

            while (reader.nextTag() == XMLStreamConstants.START_ELEMENT) {
                String localName = reader.getLocalName();
                if (localName.equals("node")) {
                    Transformer t = tf.newTransformer();
                    StringWriter st = new StringWriter();
                    t.transform(new StAXSource(reader), new StreamResult(st));
                    String xmlNode = st.toString();
                    System.out.println(nodeCount + ": " + xmlNode);
                    nodeCount++;
                }
            }
        } catch (Throwable t) {
            t.printStackTrace(System.out);
        }
        System.out.println("------------------------------------------------");
    }
}

应用程序输出,包含所有3个方案.请注意,在第一个场景中,转换的XML部分包含1个节点,而不是2.因此第二个节点完全“在转换中丢失”.

XML Input:
<root><node></node><node></node></root>
Processing:
0: <?xml version="1.0" encoding="UTF-8"?><node/>
------------------------------------------------
XML Input:
<root><node></node> <node></node></root>
Processing:
0: <?xml version="1.0" encoding="UTF-8"?><node/>
1: <?xml version="1.0" encoding="UTF-8"?><node/>
javax.xml.stream.XMLStreamException: ParseError at [row,col]:[-1,-1]
Message: found: END_DOCUMENT, expected START_ELEMENT or END_ELEMENT
    at com.sun.org.apache.xerces.internal.impl.XMLStreamReaderImpl.nextTag(XMLStreamReaderImpl.java:1247)
    at com.newedge.test.StAXTest.processXML(StAXTest.java:35)
    at com.newedge.test.StAXTest.main(StAXTest.java:21)
------------------------------------------------
XML Input:
<root><node></node> <node></node> </root>
Processing:
0: <?xml version="1.0" encoding="UTF-8"?><node/>
1: <?xml version="1.0" encoding="UTF-8"?><node/>
------------------------------------------------

解决方法:

问题是在使用transform方法之后,XMLStreamReader指向要处理的下一个XML事件(即第二个< node>开始标记或< / root>结束标记).但是,当您在while循环的顶部调用nextTag()时,您将通过另一个事件推进读者.这会导致它跳过此事件.

在您的示例中,< / node>后面有空格.结束标记,它是被跳过的空白字符数据事件.在其他情况下,正在跳过XML开始元素或结束元素事件,这就是您获得意外结果的原因.

调用变换器后,应检查阅读器的当前eventType是START_ELEMENT还是END_ELEMENT.如果是这样,变压器已经推进了阅读器,你不应该再进一步推进它.如果eventType是其他内容,或者您​​没有调用转换器,那么您可以调用nextTag()将读者推进到下一个标记.

我用以下代码替换了你的while循环:

        int eventType = reader.nextTag();
        while (eventType == XMLStreamConstants.START_ELEMENT) {
            String localName = reader.getLocalName();
            if (localName.equals("node")) {
                Transformer t = tf.newTransformer();
                StringWriter st = new StringWriter();
                t.transform(new StAXSource(reader), new StreamResult(st));
                String xmlNode = st.toString();
                System.out.println(nodeCount + ": " + xmlNode);
                nodeCount++;
                eventType = reader.getEventType();
                if (eventType != XMLStreamConstants.START_ELEMENT && eventType != XMLStreamConstants.END_ELEMENT) {
                    eventType = reader.nextTag();
                }
            } else {
                eventType = reader.nextTag();
            }

当我运行你的代码时,它给了我以下输出:

XML Input:
<root><node></node><node></node></root>
Processing:
0: <?xml version="1.0" encoding="UTF-8"?><node/>
1: <?xml version="1.0" encoding="UTF-8"?><node/>
------------------------------------------------
XML Input:
<root><node></node> <node></node></root>
Processing:
0: <?xml version="1.0" encoding="UTF-8"?><node/>
1: <?xml version="1.0" encoding="UTF-8"?><node/>
------------------------------------------------
XML Input:
<root><node></node> <node></node> </root>
Processing:
0: <?xml version="1.0" encoding="UTF-8"?><node/>
1: <?xml version="1.0" encoding="UTF-8"?><node/>
------------------------------------------------

标签:stax,java,xml-parsing
来源: https://codeday.me/bug/20190823/1696094.html