简体   繁体   English

StAX-XMLEventReader意外行为

[英]StAX - XMLEventReader unexpected behavior

I've just tried utilize StAX to parse some trivial XML document 我刚刚尝试利用StAX解析一些琐碎的XML文档

<?xml version="1.0"?>
<root>
    <Employee>
        <name>John</name>
    </Employee>
    <Employee>
        <name>Lisa</name>
    </Employee>
</root>

...but faced a problem which makes me crazy. ...但是遇到一个使我发疯的问题。 Here is the code: 这是代码:

public class Foo {

    public String name;

    @Override
    public String toString() {
        return "Foo{" + "name='" + name + '\'' + '}';
    }
}

public class StAXParserTest {

    @Test
    public void testFoo() throws Exception {
        List<Foo> result = new ArrayList<>();
        XMLEventReader eventReader = XMLInputFactory
                .newInstance()
                .createXMLEventReader(getResourceAsStream("example.xml"));
        while (eventReader.hasNext()) {
            XMLEvent event = eventReader.nextEvent();
            if (event.isStartElement()) {
                StartElement startElem = event.asStartElement();
                switch (startElem.getName().getLocalPart()) {
                    case "Employee":
                        result.add(parseFoo(eventReader));
                        break;
                }
            }
        }
        System.out.println(result);
    }

    private static Foo parseFoo(XMLEventReader eventReader) throws XMLStreamException {
        Foo foo = new Foo();
        while (true) {
            XMLEvent event = eventReader.nextEvent();
            if (event.isStartElement()) {
                switch (event.asStartElement().getName().getLocalPart()) {
                    case "name":
                        foo.name = eventReader.nextEvent().asCharacters().getData();
                        break;
                }
            }

            if (event.isEndElement() && event.asEndElement().getName().getLocalPart().equals("Foo")) {
                return foo;
            }
        }
    }

    private InputStream getResourceAsStream(String filename) throws URISyntaxException {
        return this.getClass().getClassLoader().getResourceAsStream(filename);
    }
}

There is nothing wrong it. 没错。 But if you run the test you'll get the following error. 但是,如果您运行测试,则会收到以下错误。

java.util.NoSuchElementException
    at com.sun.xml.internal.stream.XMLEventReaderImpl.nextEvent(XMLEventReaderImpl.java:88)
    at stax.StAXParserTest.parseFoo(StAXParserTest.java:40)
    at stax.StAXParserTest.testFoo(StAXParserTest.java:29)

I've spent an hour to figure out the cause. 我已经花了一个小时找出原因。 In order to solve the problem POJO class name must be EXACTLY the same as XML tag name (ie Foo.class should be renamed to Employee.class) and than it works: 为了解决该问题,POJO类名称必须与XML标记名称完全相同(即Foo.class应该重命名为Employee.class),并且可以使用:

[Employee{name='John'}, Employee{name='Lisa'}]

So my question is WHY-YYYYYY? 所以我的问题是WHY-YYYYYY? It's absolutely non-intuitive. 这是绝对不直观的。 This is not JAXB. 这不是JAXB。 Not any other object mapper. 没有任何其他对象映射器。 If I do all the work by myself than why class name matters? 如果我自己完成所有工作,那么为什么班级名称很重要?

PS Initially, it was Employee.class and <employee/> problem, but I simplified the test case to emphasize on class name. PS最初是Employee.class<employee/>问题,但我简化了测试用例以强调类名。

You must check employee as ending node, not "foo" . 您必须检查employee作为结束节点,而不是"foo"

        if (event.isEndElement() && event.asEndElement()
            .getName().getLocalPart()
            .equals("Employee")) {
            return foo;
        }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM