简体   繁体   中英

Unmarshalling the middle of xml document using jaxb

I am trying to unmarshall the middle elements of a big xml document. Currently using JAXB and Woodstox.

Example of xml middle elements that I need to unmarshall:

<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:

@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. Its being shown as 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. If there exists 15 tags before <Values> , this code isn't working.

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.

So, my questions are -- Is there anyway to increase the performance? Why wouldn't it work when its nested deep in the xml? How to get the ID value from Person attribute?

The following should help:


Why wouldn't it work when its nested deep in the 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:

    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. It is probably being used by your JAXB implementation anyways. 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 ). You could do identity checks on the strings instead of the equals methods.

     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?

By default the XML your JAXB (JSR-222) implementation will be map your ID field to an attribute called id and not ID . You can override this default as follows:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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