Handle the Middle of a XML Document with JAXB and StAX
Join the DZone community and get the full member experience.
Join For FreeXML (input.xml)
<?xml version="1.0" encoding="UTF-8"?> <S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/"> <S:Body> <ns0:findCustomerResponse xmlns:ns0="http://service.jaxws.blog/"> <return id="123"> <firstName>Jane</firstName> <lastName>Doe</lastName> </return> </ns0:findCustomerResponse> </S:Body> </S:Envelope>
Our Java model consists of a single domain class. The concepts in this example also apply to larger domain models.
package blog.stax.middle; import javax.xml.bind.annotation.*; @XmlAccessorType(XmlAccessType.FIELD) public class Customer { @XmlAttribute int id; String firstName; String lastName; }
To unmarshal from the middle of an XML document all we need to do is the following:
- Create an XMLStreamReader from the XML input (line 12).
- Advance the XMLStreamReader to the return element (lines 13-16).
- Unmarshal an instance of Customer from the XMLStreamReader (line 20)
package blog.stax.middle; import javax.xml.bind.*; import javax.xml.stream.*; import javax.xml.transform.stream.StreamSource; public class UnmarshalDemo { public static void main(String[] args) throws Exception { XMLInputFactory xif = XMLInputFactory.newFactory(); StreamSource xml = new StreamSource("src/blog/stax/middle/input.xml"); XMLStreamReader xsr = xif.createXMLStreamReader(xml); xsr.nextTag(); while(!xsr.getLocalName().equals("return")) { xsr.nextTag(); } JAXBContext jc = JAXBContext.newInstance(Customer.class); Unmarshaller unmarshaller = jc.createUnmarshaller(); JAXBElement<Customer> jb = unmarshaller.unmarshal(xsr, Customer.class); xsr.close(); Customer customer = jb.getValue(); System.out.println(customer.id); System.out.println(customer.firstName); System.out.println(customer.lastName); } }
Below is the output from running the unmarshal demo.
123 Jane Doe
Marshal Demo
- Create an XMLStreamWriter for the XML output (line 18).
- Start the document and write the outer elements (lines 19-22).
- Set the Marshaller.JAXB_FRAGMENT property on the Marshaller (line 26) to prevent the XML declaration from being written.
- Marshal an instance of Customer to the XMLStreamWriter (line 27).
- End the document, this will close any elements that have been opened (line 29).
package blog.stax.middle; import javax.xml.bind.*; import javax.xml.namespace.QName; import javax.xml.stream.*; public class MarshalDemo { public static void main(String[] args) throws Exception { Customer customer = new Customer(); customer.id = 123; customer.firstName = "Jane"; customer.lastName = "Doe"; QName root = new QName("response"); JAXBElement<Customer> je = new JAXBElement<Customer>(root, Customer.class, customer); XMLOutputFactory xof = XMLOutputFactory.newFactory(); XMLStreamWriter xsw = xof.createXMLStreamWriter(System.out); xsw.writeStartDocument(); xsw.writeStartElement("S", "Envelope", "http://schemas.xmlsoap.org/soap/envelope/"); xsw.writeStartElement("S", "Body", "http://schemas.xmlsoap.org/soap/envelope/"); xsw.writeStartElement("ns0", "findCustomerResponse", "http://service.jaxws.blog/"); JAXBContext jc = JAXBContext.newInstance(Customer.class); Marshaller marshaller = jc.createMarshaller(); marshaller.setProperty(Marshaller.JAXB_FRAGMENT, true); marshaller.marshal(je, xsw); xsw.writeEndDocument(); xsw.close(); } }
Below is the output from running the marshal demo. Note that the output from running the demo code will appear on a single line, I have formatted the output here to make it easier to read.
<?xml version="1.0" encoding="UTF-8"?> <S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/"> <S:Body> <ns0:findCustomerResponse xmlns:ns0="http://service.jaxws.blog/"> <return id="123"> <firstName>Jane</firstName> <lastName>Doe</lastName> </return> </ns0:findCustomerResponse> </S:Body> </S:Envelope>
Published at DZone with permission of Blaise Doughan, DZone MVB. See the original article here.
Opinions expressed by DZone contributors are their own.
Comments