Hi I have an XML structure like this:
<?xml version="1.0" encoding="UTF-8"?>
<response>
<result>
<name>Chrome</name>
<version>2</version>
</result>
<result>
<name>IE</name>
<version>8</version>
</result>
</response>
I am trying to use staxx to parse out just the stuff in the middle with JAXB. The problem I am getting is that it isn't getting all result elements. See out put below:
Output:
response
result
name
version
How can I get all result objects, the inside could be any generic object I pass in? Also, is there a way once I parse the object with jaxb, to advance the staxx iterator to the end of , (since there isnt much point in parsing the rest, once I have the object).
private static <T> List<T> unmarshallCreateResponseObject(Class<T> clazz, String xml) throws JAXBException, XMLStreamException
{
List<T> list = new ArrayList<T>();
XMLInputFactory xif = XMLInputFactory.newFactory();
StringReader stringReader = new StringReader(xml);
XMLStreamReader xsr = xif.createXMLStreamReader(stringReader);
while (xsr.hasNext()) {
int eventType = xsr.next();
if(eventType == XMLStreamReader.START_ELEMENT){
System.out.println(xsr.getLocalName());
if(xsr.getLocalName().equals("result"))
{
JAXBContext jc = JAXBContext.newInstance(clazz);
Unmarshaller unmarshaller = jc.createUnmarshaller();
JAXBElement<T> jb = unmarshaller.unmarshal(xsr, clazz);
list.add(jb.getValue());
}
}
}
xsr.close();
return list;
}
From the unmarshaller documentation (emphasis mine)
<T> JAXBElement<T> Unmarshaller.unmarshal(XMLStreamReader reader, Class declaredType)Unmarshal root element to JAXB mapped declaredType and return the resulting content tree.
This method implements unmarshal by declaredType.
This method assumes that the parser is on a START_DOCUMENT or START_ELEMENT event. Unmarshalling will be done from this start event to the corresponding end event. If this method returns successfully, the reader will be pointing at the token right after the end event.
We can see from your example that the unmarshal
call starts at a START_ELEMENT
event, so when the call is done, the reader
will be at the next event after the STOP_ELEMENT
, which may be the START_ELEMENT
of the next <result>
.
At this point, your while
loop executes, detects that there are still events in the reader, so steps in, and calls in xsr.next()
, which leaves your parser at START_ELEMENT
of <name>
, which fails your if
test.
So your code fails, because you accidentaly "skip over" the opening of the second <result>
tag. (If I'm right, your code should actually skip one out of two <result>
instances).