There are many XML libraries around that help with XML processing, such as jdom or dom4j, but the standard JDK comes with everything you need. Lets get started!
Getting a Document
The first step in processing XML is to create a Document from the raw XML. The Document is the central class for XML processing. We use a DocumentBuilder to parse XML into a Document. The builder has several overloaded parse methods allowing you to create a Document from a File, InputStream, InputSource or a URI. Here we are using a file.
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
File file = new File("employees.xml");
Document doc = builder.parse(file);
DocumentBuilder builder = factory.newDocumentBuilder();
File file = new File("employees.xml");
Document doc = builder.parse(file);
In this example we're going to work with a basic XML file, employees;
<employees>
<employee id="1">
<name>Fred</name>
<age>20</age>
<department>Sales</department>
</employee>
<employee id="2">
<name>Bob</name>
<age>30</age>
<department>Sales</department>
</employee>
<employee id="3">
<name>Jim</name>
<age>23</age>
<department>Marketing</department>
</employee>
</employees>
<employee id="1">
<name>Fred</name>
<age>20</age>
<department>Sales</department>
</employee>
<employee id="2">
<name>Bob</name>
<age>30</age>
<department>Sales</department>
</employee>
<employee id="3">
<name>Jim</name>
<age>23</age>
<department>Marketing</department>
</employee>
</employees>
Working with the Document
Now we have our Document, we can extract data from it using XPath. XPath is a powerful query language for selecting nodes from an XML Document. Lets find the name of the employee with an ID of 1.
XPathFactory xpFactory = XPathFactory.newInstance();
XPath xpath = xpFactory.newXPath();
String qry = "/employees/employee[@id = '1']/name";
String name = (String)xpath.evaluate(qry, doc, XPathConstants.STRING);
System.out.println(name);
XPath xpath = xpFactory.newXPath();
String qry = "/employees/employee[@id = '1']/name";
String name = (String)xpath.evaluate(qry, doc, XPathConstants.STRING);
System.out.println(name);
When this code is run, it will output Fred, which is the name of the employee with an id attribute of '1'. Now lets get all the employee nodes in the sales department.
xpath.reset();
qry = "/employees/employee[department = 'Sales']";
NodeList employees = (NodeList)xpath.evaluate(qry, doc, XPathConstants.NODESET);
System.out.println("Employees in Sales department;");
for (int i=0; i<employees.getLength(); i++) {
Element employee = (Element)employees.item(i);
name = employee.getElementsByTagName("name").item(0).getTextContent();
String age = employee.getElementsByTagName("age").item(0).getTextContent();
String id = employee.getAttribute("id");
System.out.format("%2$s - %1$s age %3$s\n", name, id, age);
}
qry = "/employees/employee[department = 'Sales']";
NodeList employees = (NodeList)xpath.evaluate(qry, doc, XPathConstants.NODESET);
System.out.println("Employees in Sales department;");
for (int i=0; i<employees.getLength(); i++) {
Element employee = (Element)employees.item(i);
name = employee.getElementsByTagName("name").item(0).getTextContent();
String age = employee.getElementsByTagName("age").item(0).getTextContent();
String id = employee.getAttribute("id");
System.out.format("%2$s - %1$s age %3$s\n", name, id, age);
}
In the above example we get a NodeList and loop over it to create a report of the employees in the Sales department;
Employees in Sales department;
1 - Fred age 20
2 - Bob age 30
1 - Fred age 20
2 - Bob age 30
Creating a new Document
Now lets look at creating a new Document from scratch. We use a DocumentBuilder to create a new empty Document, then we create some elements and build up the DOM tree.
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document doc = builder.newDocument();
Element order = doc.createElement("order");
order.setAttribute("number", "1");
doc.appendChild(order);
Element total = doc.createElement("total");
total.setTextContent("10.00");
order.appendChild(total);
Element status = doc.createElement("status");
status.setTextContent("dispatched");
order.appendChild(status);
DocumentBuilder builder = factory.newDocumentBuilder();
Document doc = builder.newDocument();
Element order = doc.createElement("order");
order.setAttribute("number", "1");
doc.appendChild(order);
Element total = doc.createElement("total");
total.setTextContent("10.00");
order.appendChild(total);
Element status = doc.createElement("status");
status.setTextContent("dispatched");
order.appendChild(status);
Now we have a small order Document! In order to see what a Document looks like we can output the Document to the console using a Transformer.
TransformerFactory tFactory = TransformerFactory.newInstance();
Transformer transformer = tFactory.newTransformer();
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
DOMSource source = new DOMSource(order);
StreamResult result = new StreamResult(System.out);
transformer.transform(source, result);
Transformer transformer = tFactory.newTransformer();
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
DOMSource source = new DOMSource(order);
StreamResult result = new StreamResult(System.out);
transformer.transform(source, result);
which gives us the output;
<?xml version="1.0" encoding="UTF-8"?>
<order number="1">
<total>10.00</total>
<status>dispatched</status>
</order>
<order number="1">
<total>10.00</total>
<status>dispatched</status>
</order>