This example shows you how to parse XML into a simple set of value objects. First consider the set of XML documents that would be described by the following pseudo-grammar.
<document xmlns="ns://standardOrder">
<customer id="int"><name>string</name><company>string</company></customer>*
<order><customerIdRef>int</customerIdRef><part>string</part><ship-date>date</ship-date></order>*
</document>The StAX API allows you to write a simple recursive descent parser that processes this file type. First you would design the objects that will hold the data.
// OrderDocument.java
package examples.order;
import java.util.*;
public class OrderDocument {
public ArrayList orders = new ArrayList();
public ArrayList customers = new ArrayList();
public OrderDocument(){}
public void addOrder(Order o) {
orders.add(o);
}
public void addCustomer(Customer c) {
customers.add(c);
}
public String toString() {
StringBuffer b = new StringBuffer();
b.append("Order[\n");
Iterator i = customers.iterator();
while(i.hasNext()) b.append("\t"+i.next()+"\n");
i = orders.iterator();
while(i.hasNext()) b.append("\t"+i.next()+"\n");
b.append("]Order\n");
return b.toString();
}
}
This class holds the order document that will be processed.// Order.java
package examples.order;
public class Order {
private int idRef;
private String part;
private String date;
public Order(int idRef, String part, String shipDate){
this.idRef = idRef;
this.part = part;
this.date = shipDate;
}
public String toString() {
return "["+idRef+"]["+part+"]["+date+"]";
}
}
// Customer.java
package examples.order;
public class Customer {
private int id;
private String name;
private String company;
public Customer(int id,
String name,
String company) {
this.id = id;
this.name = name;
this.company = company;
}
public String toString() {
return "["+id+"]["+name+"]["+company+"]";
}
}
The above classes hold orders & customers. The following instance document can be parsed easily with StAX.<o:document xmlns:o="ns://standardOrder">
<o:customer o:id="1">
<o:name>Dave Smith</o:name>
<o:company>myParts.com</o:company>
</o:customer>
<o:customer o:id="2">
<o:name>Patty Smith</o:name>
<o:company>myParts.com</o:company>
</o:customer>
<o:order>
<o:customerIdRef>1</o:customerIdRef>
<o:part>red bike</o:part>
<o:ship-date>10/30/2003</o:ship-date>
</o:order>
<o:order>
<o:customerIdRef>2</o:customerIdRef>
<o:part>blue bike</o:part>
<o:ship-date>10/30/2003</o:ship-date>
</o:order>
<o:order>
<o:customerIdRef>2</o:customerIdRef>
<o:part>green bike</o:part>
<o:ship-date>11/15/2003</o:ship-date>
</o:order>
</o:document>
The class to parse this document is OrderProcessor class://OrderProcessor.java
package examples.order;
import javax.xml.stream.*;
public class OrderProcessor {
private final String ns = "ns://standardOrder";
public OrderProcessor(){}
public void toStartTag(XMLStreamReader r)
throws XMLStreamException
{
while(!r.isStartElement()&& r.hasNext())
r.next();
}
public OrderDocument parseDocument(XMLStreamReader r)
throws XMLStreamException
{
OrderDocument doc = new OrderDocument();
toStartTag(r);
if ("document".equals(r.getLocalName()) &&
ns.equals(r.getNamespaceURI())) {
r.next();
toStartTag(r);
while ("customer".equals(r.getLocalName()) &&
ns.equals(r.getNamespaceURI())) {
doc.addCustomer(parseCustomer(r));
r.next();
toStartTag(r);
}
while("order".equals(r.getLocalName()) &&
ns.equals(r.getNamespaceURI())) {
doc.addOrder(parseOrder(r));
r.next();
toStartTag(r);
}
}
return doc;
}
public Customer parseCustomer(XMLStreamReader r)
throws XMLStreamException
{
int id=-1;
String name="defaultName";
String company="defaultCompany";
id = Integer.parseInt(r.getAttributeValue(ns,"id"));
r.next(); toStartTag(r);
if ("name".equals(r.getLocalName())) {
r.next();
name = r.getText();
r.next(); toStartTag(r);
}
if ("company".equals(r.getLocalName())) {
r.next();
company = r.getText();
}
return new Customer(id,name,company);
}
public Order parseOrder(XMLStreamReader r)
throws XMLStreamException
{
int idRef=-1;
String part="defaultPart";
String shipDate="1/1/03";
r.next(); toStartTag(r);
if ("customerIdRef".equals(r.getLocalName())) {
r.next();
idRef = Integer.parseInt(r.getText());
r.next(); toStartTag(r);
}
if ("part".equals(r.getLocalName())) {
r.next();
part = r.getText();
r.next(); toStartTag(r);
}
if ("ship-date".equals(r.getLocalName())) {
r.next();
shipDate = r.getText();
}
return new Order(idRef,part,shipDate);
}
public static void main(String args[])
throws Exception
{
OrderProcessor processor = new OrderProcessor();
XMLStreamReader r = XMLInputFactory.newInstance().createXMLStreamReader(
new java.io.FileInputStream(args[0])
);
OrderDocument doc = processor.parseDocument(r);
System.out.println(doc);
}
}
The main of this simple class creates an XMLStreamReader and loads an order document from a file. The factory uses the default implementation of the XMLInputFactory to find an instance of XMLStreamReader. This is passed to the parse* methods which return objects that are represented in the XML. The main thing to note is that you can pass around an instance of the XMLStreamReader to the different methods and let them figure out what to do (pull more events) or simply return.Coming Soon:
How to write XML serialization interfaces
Simple parsing example
Data binding example
Using events



