com.pushtotest.tool.xml
Class PullUnmarshaller

java.lang.Object
  extended by com.pushtotest.tool.xml.PullUnmarshaller

public final class PullUnmarshaller
extends java.lang.Object

Wraps Unmarshaller and provide a functionality to unmarshal from a XmlPullParser.

This is particularly useful to unmarshal just a part of a document into a JAXB object.

It is often the case that you don't need complete random access to the entire document. Instead, you usually just need random access to a limited region of XML. In this scenario, it is typically a waste of resources to bind the entire document into a single JAXB object tree. It will consume more memory, it will cause a greater latency.

In some cases, your interesting XML document is contained inside an "envelope", which you are not so interested in. In this scenario, this class can be used to just bind the real meat to a JAXB object. In this way, you don't need to compile a schema that corresponds to the envelope.

Example

Consider the following address book XML:


 <addressBook>
   <contact>
     <name>John Doe</name>
     <email>john@acme.com</email>
   </contact>
   <contact>
     <name>Jane Smith</name>
     <email>jane@acme.org</email>
   </contact>
   ...
 </addressBook>
 

Suppose the address book is very long and your program is just looking for the record of "Jane Smith". Unmarshalling the whole document is easy, but it forces the entire document to be loaded, which consumes more memory.

This document can be processed in the following way:


 // set up a parser
 XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
 factory.setNamespaceAware(true);
 XmlPullParser xpp = factory.newPullParser();
 
 // create an unmarshaller
 PullUnmarshaller u = new PullUnmarshaller(jaxbContext);
 
 xpp.setInput( new FileInputStream("contact.xml"), null );
 xpp.nextTag();   // move to the root element
 xpp.require(XmlPullParser.START_TAG,"","addressBook"); // check the root tag name
 xpp.nextTag();   // move to the first <contact> element.
 
 while(xpp.getEventType()==XmlPullParser.START_TAG) {
    // unmarshall one <contact> element into a JAXB Contact object
    Contact contact = (Contact)u.unmarshalSubTree(xpp);
    processContact(contact);
  
    if( xpp.getEventType()==XmlPullParser.TEXT)
       xpp.next();    // skip the whitespace between <contact>s.
 }
 

Note that the unmarshaller will think that the <contact> element is the root element of a document, so it is important for the <contact> element to be declared as a global element.

It unmarshals one <contact> at a time, then process it. The added benefit is that you can stop the processing as soon as you find the info you are looking for. This makes the program a lot (average of roughly 2x) faster.


Constructor Summary
PullUnmarshaller(javax.xml.bind.JAXBContext context)
          Constructs a PullUnmarshaller from a JAXBContext.
PullUnmarshaller(javax.xml.bind.Unmarshaller _unmarshaller)
          Constrcuts a PullUnmarshaller by wrapping an Unmarshaller instance.
 
Method Summary
 java.lang.Object unmarshalSubTree(org.xmlpull.v1.XmlPullParser parser)
          Reads a XML sub-tree and unmarshals it into a JAXB object.
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Constructor Detail

PullUnmarshaller

public PullUnmarshaller(javax.xml.bind.JAXBContext context)
                 throws javax.xml.bind.JAXBException
Constructs a PullUnmarshaller from a JAXBContext.

This is the equivalent of new PullUnmarshaller(context.createUnmarshaller());

Throws:
javax.xml.bind.JAXBException

PullUnmarshaller

public PullUnmarshaller(javax.xml.bind.Unmarshaller _unmarshaller)
Constrcuts a PullUnmarshaller by wrapping an Unmarshaller instance.

All the real work of unmarshalling is done through the specified unmarshaller. So configure it appropriately and don't reuse this unmarshaller instance while this PullUnmarshaller is in use.

Method Detail

unmarshalSubTree

public java.lang.Object unmarshalSubTree(org.xmlpull.v1.XmlPullParser parser)
                                  throws java.lang.IllegalStateException,
                                         javax.xml.bind.JAXBException
Reads a XML sub-tree and unmarshals it into a JAXB object.

the parser must point to a start element. This method will read the whole sub-tree, send it to the JAXB unmarshaller (which was specfied to the constructor), then return the obtained object.

After the successful completion of this method, the parser will point to the event next to the end element of the sub-tree.

If a processing fails, the parser will be left at somewhere in the middle of the sub-tree.

Parameters:
parser - A pull parser from which an object will be unmarshalled. The parser must be at the start element. IOW, pp.getEventType() == XmlPullParser.START_TAG has to be true.
Returns:
Always return a non-null valid object.
Throws:
java.lang.IllegalStateException - If the parser is not set at a start element event, this exception will be thrown.
javax.xml.bind.JAXBException - In case of any XML wellformedness error, IO error, and JAXB unmarshalling errors. Before this exception is thrown, it is reported to the ValidationEventHandler of the unmarshaller first.