Unmarshalling the middle of an xml document with jaxb

I am trying to parse the middle elements of a large XML document. Currently used by JAXB and Woodstox.

An example of the middle xml elements that I need to undo:

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

I am using jaxb classes:

 @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 can disable all values ​​except ID. It is 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 only works when <Values> nested 5-6 levels from the root. If there are 15 tags before <Values> , this code does not work.

Also, it is relatively slow compared to using only JAXB and unmarshalling all elements, but this will require me to create objects for data that will never be used.

So my questions is, is there a way to improve performance? Why not work when it's nested in xml? How to get ID value from Person attribute?

+4
source share
1 answer

The following is help:


Why not work when it's nested in XML?

If you are not working, you mean throwing an exception, for example:

 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) 

You can change the code that XmlStreamReader promotes to:

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

Is there a way to improve performance?

StAX is a very fast way to parse an XML document. This is probably used in your JAXB implementation anyway. String comparison can be slow. Since you are using Woodstox and it puts the names of the elements (see Section 6.1. Interpretation of strings: http://woodstox.codehaus.org/FAQ ). You could do identity checks on strings instead of 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 ID value from Person attribute?

By default, XML, your JAXB implementation (JSR-222) will map your ID field to an ID attribute, not an ID . You can override this default value as follows:

 @XmlAttribute(name="ID") private String ID; 
+6
source

All Articles