简体   繁体   English

使用jaxb解组xml文档的中间部分

[英]Unmarshalling the middle of xml document using jaxb

I am trying to unmarshall the middle elements of a big xml document. 我试图解组一个大的xml文档的中间元素。 Currently using JAXB and Woodstox. 目前正在使用JAXB和Woodstox。

Example of xml middle elements that I need to unmarshall: 我需要解组的xml中间元素的示例:

<Values>
   <Person ID="ABC">
    <FirstName>Shawn</FirstName>
    <LastName>Mark</LastName>
    <Age>3</Age>
   </Person>
   <Person ID="DEF">
        <FirstName>John</FirstName>
        <LastName>Durell</LastName>
        <Age>4</Age>
    </Person>
</Values>

The jaxb classes that I use are: 我使用的jaxb类是:

@XmlRootElement(name = "Values")
@XmlAccessorType(XmlAccessType.FIELD)
public class Attributes
{
    @XmlElement(name = "Person")
    private ArrayList<Person> persons;

    public ArrayList<Person> getPersons()
    {
        return persons;
    }
}


@XmlAccessorType(XmlAccessType.FIELD)
public class Person
{
    @XmlAttribute
    private String ID;

    @XmlElement(name = "FirstName")
    private String firstName;

    @XmlElement(name = "LastName")
    private String lastName;

    @XmlElement(name = "Age")
    private String age;
}

I am able to unmarshall all values except the ID. 我可以解除除ID之外的所有值。 Its being shown as null. 它被显示为null。

Here is the code: 这是代码:

final XMLInputFactory xif = XMLInputFactory.newInstance();
final StreamSource xml = new StreamSource(pathToxmlFile);
XMLStreamReader xsr;
xsr = xif.createXMLStreamReader(xml);
xsr.nextTag();
while (!xsr.getLocalName().equals("Values"))
{
     xsr.nextTag();
}

final JAXBContext jc = JAXBContext.newInstance(Attributes.class);
final Unmarshaller unmarshaller = jc.createUnmarshaller();
final JAXBElement<Attributes> jb = unmarshaller.unmarshal(xsr, Attributes.class);

The above code is working only when the <Values> is nested 5-6 levels from the root. 上面的代码仅在<Values>从根目录嵌套5-6级时起作用。 If there exists 15 tags before <Values> , this code isn't working. 如果在<Values>之前存在15个标记,则此代码不起作用。

Also its comparatively very slow when compared to just only using JAXB and unmarshalling all elements, but that would require me to create objects for data which will never be used. 与仅使用JAXB和解组所有元素相比,它相对非常慢,但这需要我为永远不会使用的数据创建对象。

So, my questions are -- Is there anyway to increase the performance? 所以,我的问题是 - 无论如何都要提高性能? Why wouldn't it work when its nested deep in the xml? 当它嵌套在xml深处时为什么不能工作? How to get the ID value from Person attribute? 如何从Person属性中获取ID值?

The following should help: 以下应该有所帮助:


Why wouldn't it work when its nested deep in the xml? 当它嵌套在xml深处时为什么不能工作?

If by not working you mean throwing an exception like: 如果不工作就意味着抛出一个例外:

Exception in thread "main" javax.xml.stream.XMLStreamException: ParseError at [row,col]:[4,13]
Message: found: CHARACTERS, expected START_ELEMENT or END_ELEMENT
    at com.sun.org.apache.xerces.internal.impl.XMLStreamReaderImpl.nextTag(XMLStreamReaderImpl.java:1247)
    at blog.stax.middle.UnmarshalDemo.main(UnmarshalDemo.java:15)

The you could change the code that advances the XmlStreamReader to: 您可以更改将XmlStreamReader到的代码:

    while(xsr.hasNext()) {
        if(xsr.isStartElement() && xsr.getLocalName().equals("Values")) {
            break;
        }
        xsr.next();
    }

Is there anyway to increase the performance? 反正有提高性能吗?

StAX is a very fast way to parse an XML document. StAX是一种解析XML文档的快速方法。 It is probably being used by your JAXB implementation anyways. 它可能正在被您的JAXB实现使用。 String comparison can be slow. 字符串比较可能很慢。 Since you are using Woodstox and it interns element names (see: section 6.1 String interning: http://woodstox.codehaus.org/FAQ ). 由于您使用的是Woodstox并且它实际上是元素名称(请参阅:第6.1节字符串实习: http ://woodstox.codehaus.org/FAQ)。 You could do identity checks on the strings instead of the equals methods. 您可以对字符串进行身份检查,而不是使用equals方法。

     if(Boolean.TRUE.equals(xsr.getProperty("org.codehaus.stax2.internNames"))) {
        while(xsr.hasNext()) {
            if(xsr.isStartElement() && xsr.getLocalName() == "return") {
                break;
            }
            xsr.next();
        }
    } else {
        while(xsr.hasNext()) {
            if(xsr.isStartElement() && xsr.getLocalName().equals("return")) {
                break;
            }
            xsr.next();
        }
    }

How to get the ID value from Person attribute? 如何从Person属性中获取ID值?

By default the XML your JAXB (JSR-222) implementation will be map your ID field to an attribute called id and not ID . 默认情况下,您的JAXB(JSR-222)实现的XML将您的ID字段映射到名为id而不是ID的属性。 You can override this default as follows: 您可以按如下方式覆盖此默认值:

@XmlAttribute(name="ID")
private String ID;

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

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