Is There an Easier Way to Parse Xml in Java

Is there an easier way to parse XML in Java?

There are two different types of processors for XML in Java (3 actually, but one is weird). What you have is a SAX parser and what you want is a DOM parser. Take a look at http://www.mkyong.com/java/how-to-read-xml-file-in-java-dom-parser/ for how to use the DOM parser. DOM will create a tree which you can navigate pretty easily. SAX is best for large documents but DOM is much easier if slower and much more memory intensive.

Simplest way to parse this XML in Java?

The simplest way to search for what you are looking for, would be XPath.

try {

//Load the XML File
DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance();
domFactory.setNamespaceAware(true);
DocumentBuilder builder = domFactory.newDocumentBuilder();
Document configuration = builder.parse("configs.xml");

//Create an XPath expression
XPathFactory xpathFactory = XPathFactory.newInstance();
XPath xpath = xpathFactory.newXPath();
XPathExpression expr = xpath.compile("//ConfigGroup/ValueString[@Name='Host']/text()");

//Execute the XPath query
Object result = expr.evaluate(configuration, XPathConstants.NODESET);
NodeList nodes = (NodeList) result;

//Parse the results
for (int i = 0; i < nodes.getLength(); i++) {
System.out.println(nodes.item(i).getNodeValue());
}
} catch (ParserConfigurationException e) {
System.out.println("Bad parser configuration");
e.printStackTrace();
} catch (SAXException e) {
System.out.println("SAX error loading the file.");
e.printStackTrace();
} catch (XPathExpressionException e) {
System.out.println("Bad XPath Expression");
e.printStackTrace();
} catch (IOException e) {
System.out.println("IO Error reading the file.");
e.printStackTrace();
}

The XPath expression

"//ConfigGroup/ValueString[@Name='Host']/text()"

looks for ConfigGroup elements anywhere in your XML, then finds ValueString elements within the ConfigGroup elements, that have a Name attribute with the value "Host". @Name=Host is like a filter for elements with the name ValueString. And text() at the end, returns the text node of the selected elements.

Better way to parse xml

Here's an example of using JAXB with StAX.

Input document:

<?xml version="1.0" encoding="UTF-8"?>
<Personlist xmlns="http://example.org">
<Person>
<Name>Name 1</Name>
<Address>
<StreetAddress>Somestreet</StreetAddress>
<PostalCode>00001</PostalCode>
<CountryName>Finland</CountryName>
</Address>
</Person>
<Person>
<Name>Name 2</Name>
<Address>
<StreetAddress>Someotherstreet</StreetAddress>
<PostalCode>43400</PostalCode>
<CountryName>Sweden</CountryName>
</Address>
</Person>
</Personlist>

Person.java:

@XmlRootElement(name = "Person", namespace = "http://example.org")
public class Person {
@XmlElement(name = "Name", namespace = "http://example.org")
private String name;
@XmlElement(name = "Address", namespace = "http://example.org")
private Address address;

public String getName() {
return name;
}

public Address getAddress() {
return address;
}
}

Address.java:

public class Address {
@XmlElement(name = "StreetAddress", namespace = "http://example.org")
private String streetAddress;
@XmlElement(name = "PostalCode", namespace = "http://example.org")
private String postalCode;
@XmlElement(name = "CountryName", namespace = "http://example.org")
private String countryName;

public String getStreetAddress() {
return streetAddress;
}

public String getPostalCode() {
return postalCode;
}

public String getCountryName() {
return countryName;
}
}

PersonlistProcessor.java:

public class PersonlistProcessor {
public static void main(String[] args) throws Exception {
new PersonlistProcessor().processPersonlist(PersonlistProcessor.class
.getResourceAsStream("personlist.xml"));
}

// TODO: Instead of throws Exception, all exceptions should be wrapped
// inside runtime exception
public void processPersonlist(InputStream inputStream) throws Exception {
JAXBContext jaxbContext = JAXBContext.newInstance(Person.class);
XMLStreamReader xss = XMLInputFactory.newFactory().createXMLStreamReader(inputStream);
// Create unmarshaller
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
// Go to next tag
xss.nextTag();
// Require Personlist
xss.require(XMLStreamReader.START_ELEMENT, "http://example.org", "Personlist");
// Go to next tag
while (xss.nextTag() == XMLStreamReader.START_ELEMENT) {
// Require Person
xss.require(XMLStreamReader.START_ELEMENT, "http://example.org", "Person");
// Unmarshall person
Person person = (Person)unmarshaller.unmarshal(xss);
// Process person
processPerson(person);
}
// Require Personlist
xss.require(XMLStreamReader.END_ELEMENT, "http://example.org", "Personlist");
}

private void processPerson(Person person) {
System.out.println(person.getName());
System.out.println(person.getAddress().getCountryName());
}
}

Best way to parse an XML String in Java?

To answer your question directly - to my knowledge, there is not a better way. The input source is used because it is more universal and can handle input from a file, a String or across the wire is my understanding.

You could also try using the SAX Xml parser - it is a little more basic, and uses the Visitor Pattern, but it gets the job done and for smallish data sets and simple XML schemas it is pretty easy to use. SAX is also included with the core JRE.

Fastest and optimized way to read the xml

Using ReadAndPrintXMLFileWithStAX below, when I compare with ReadAndPrintXMLFileWithSAX from the answer given by gontard the StAX approach is faster. My test involved running both sample code 500000 times on JDK 1.7.0_07 for the Mac.

ReadAndPrintXMLFileWithStAX:  103 seconds
ReadAndPrintXMLFileWithSAX: 125 seconds

ReadAndPrintXMLFileWithStAX (using Java SE 7)

Below is a more optimized StAX (JSR-173) example using XMLStreamReader instead of XMLEventReader.

import java.io.FileInputStream;
import java.io.InputStream;
import javax.xml.stream.*;

public class ReadAndPrintXMLFileWithStAX {

public static void main(String argv[]) throws Exception {
XMLInputFactory inputFactory = XMLInputFactory.newInstance();
InputStream in = new FileInputStream("book.xml");
XMLStreamReader streamReader = inputFactory.createXMLStreamReader(in);
streamReader.nextTag(); // Advance to "book" element
streamReader.nextTag(); // Advance to "person" element

int persons = 0;
while (streamReader.hasNext()) {
if (streamReader.isStartElement()) {
switch (streamReader.getLocalName()) {
case "first": {
System.out.print("First Name : ");
System.out.println(streamReader.getElementText());
break;
}
case "last": {
System.out.print("Last Name : ");
System.out.println(streamReader.getElementText());
break;
}
case "age": {
System.out.print("Age : ");
System.out.println(streamReader.getElementText());
break;
}
case "person" : {
persons ++;
}
}
}
streamReader.next();
}
System.out.print(persons);
System.out.println(" persons");
}

}

Output

First Name : Kiran
Last Name : Pai
Age : 22
First Name : Bill
Last Name : Gates
Age : 46
First Name : Steve
Last Name : Jobs
Age : 40
3 persons

Best XML parser for Java

If speed and memory is no problem, dom4j is a really good option. If you need speed, using a StAX parser like Woodstox is the right way, but you have to write more code to get things done and you have to get used to process XML in streams.



Related Topics



Leave a reply



Submit