Share this page 

Parse with XPathTag(s): XML


[J2SE 1.5]

Consider the following XML data file (howto.xml)

<?xml version="1.0"?>
<howto>
  <topic name="Java">
      <url>http://www.rgagnon.com/topics/java-xml.html</url>
  </topic>
  <topic name="PowerBuilder">
      <url>http://www.rgagnon.com/topics/pb-common.html</url>
      <url>http://www.rgagnon.com/topics/pb-pfc.html</url>
  </topic>
  <topic name="Javascript">
        <url>http://www.rgagnon.com/topics/js-language.html</url>
  </topic>
  <topic name="VBScript">
       <url>http://www.rgagnon.com/topics/wsh-vbs.html</url>
  </topic>
</howto>
To list the topics :
import java.io.File;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.xpath.*;

import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;

public class SimpleXPath {
  public static void main(String[] args) throws Exception {
    XPath xpath = XPathFactory.newInstance().newXPath();
    String xpathExpression = "/howto/topic/@name";
    InputSource inputSource = new InputSource("howto.xml");

    NodeList nodes = (NodeList) xpath.evaluate
       (xpathExpression, inputSource, XPathConstants.NODESET);

    int j = nodes.getLength();

    for (int i = 0; i < j; i++) {
        System.out.println(nodes.item(i).getTextContent());
    }
    /*
    output :
       Java
       PowerBuilder
       Javascript
       VBScript
    */
  }
}
Select the topic Powerbuilder then list the urls :
import java.io.File;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.xpath.*;

import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;

public class SimpleXPath2 {
  public static void main(String[] args) throws Exception {
    XPath xpath = XPathFactory.newInstance().newXPath();
    String topicExpression = "/howto/topic[@name='PowerBuilder']";
    InputSource inputSource = new InputSource("howto.xml");

    // get nodes with the topic PowerBuilder
    NodeList nodes = (NodeList) xpath.evaluate
       (topicExpression, inputSource, XPathConstants.NODESET);

    // output the text content of this node and its descendants.
    //   (includes empty LF because of empty comment (#text))
    System.out.println(nodes.item(0).getTextContent());
    /*
    output :
          http://www.rgagnon.com/topics/pb-common.html
          http://www.rgagnon.com/topics/pb-pfc.html
    */
    // display only the "url" nodes for PowerBuidler
    NodeList urls = nodes.item(0).getChildNodes();
    int j = urls.getLength();
    for (int i = 0; i < j ; i++) {
        if (urls.item(i).getNodeName().equals("url")) {
            System.out.println("url :" + urls.item(i).getTextContent());
        }
    }
    /*
    output :
       url :http://www.rgagnon.com/topics/pb-common.html
       url :http://www.rgagnon.com/topics/pb-pfc.html
    */
  }
}

If your XML is in a String (not in a File) then you need to get an InputStream from it.
import java.io.ByteArrayInputStream;
import java.io.InputStream;

...

String xml = "<?xml version="1.0"?>"
           + " <howto>"
           + "   <topic name="Java">"
           ...
           + "</howto>";


InputStream is = new ByteArrayInputStream(xml.getBytes()); 
XPath xpath = XPathFactory.newInstance().newXPath();
String xpathExpression = "/howto/topic[@name='PowerBuilder']";
InputSource inputSource = new InputSource(is);
NodeList nodes = (NodeList) xpath.evaluate
    (topicExpression, inputSource, XPathConstants.NODESET);
...
You may need to pass the required encoding to the String.getBytes() method. See this HowTo
Consider this XML :
<?xml version="1.0" encoding="UTF-8"?>
<UDSObjectList>
  <UDSObject>
    <Handle>chg_tpl:400004</Handle>
    <Attributes>
      <Attribute DataType="2001">
        <AttrName>id</AttrName>
        <AttrValue>400004</AttrValue>
     </Attribute>
    <Attribute DataType="2002">
      <AttrName>persistent_id</AttrName>
      <AttrValue>chg_tpl:400004</AttrValue>
    </Attribute>
</Attributes>
</UDSObject>
</UDSObjectList>
If we want the Handle text value then we don't need to retrieve the NODESET, only the TEXT.
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathFactory;
import org.xml.sax.InputSource;

...

String xml = "<?xml version="1.0" encoding="UTF-8"?>"
           + "<UDSObjectList>"
           ...
           + "</UDSObjectList>";

...

InputStream is = new ByteArrayInputStream(xml.getBytes("UTF8"));
XPath xpath = XPathFactory.newInstance().newXPath();
String xpathExpression = "/UDSObjectList/UDSObject/Handle";
InputSource inputSource = new InputSource(is);
String handle = xpath.evaluate(xpathExpression, inputSource);
System.out.println(handle);
/*
  output :
     chg_tpl:400004
*/

One last example. Suppose we have an XML file containing SQL Statements.
 <queries>
    <query id="getUserByName">select * from users where name=?</query>
    <query id="getUserByEmail">select * from users where email=?</query>
 </queries>
 
To retrieve a SELECT
 import javax.xml.xpath.XPath;
 import javax.xml.xpath.XPathFactory;
 import org.xml.sax.InputSource;

 public class Test {
   public static void main(String[] args) throws Exception {
     System.out.println(getQuery("getUserByName"));
     System.out.println(getQuery("getUserByEmail"));
   }

   public static String getQuery (String id) throws Exception {
     XPath xpath = XPathFactory.newInstance().newXPath();
     // in this example, sql.xml is loaded from the classpath
     InputSource is = new InputSource(Test.class.getResourceAsStream("/sql.xml"));
     return xpath.evaluate("/queries/query[@id='" + id +"']", is);
   }
}
/* output :
select * from users where name=?
select * from users where email=?
*/