56

I am new to XML. I want to read the following XML on the basis of request name. Please help me on how to read the below XML in Java -

<?xml version="1.0"?>
    <config>
        <Request name="ValidateEmailRequest">
            <requestqueue>emailrequest</requestqueue>
            <responsequeue>emailresponse</responsequeue>
        </Request>
        <Request name="CleanEmail">
            <requestqueue>Cleanrequest</requestqueue>
            <responsequeue>Cleanresponse</responsequeue>
        </Request>
    </config>
Hari
  • 310
  • 3
  • 14
Sameek Mishra
  • 9,174
  • 31
  • 92
  • 118
  • 1
    Err, this is very similar to your other question here.. http://stackoverflow.com/questions/4013687/how-to-append-a-new-value-in-xml-using-java/4013881#4013881 – William Nov 02 '10 at 11:03

10 Answers10

76

If your XML is a String, Then you can do the following:

String xml = ""; //Populated XML String....

DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document document = builder.parse(new InputSource(new StringReader(xml)));
Element rootElement = document.getDocumentElement();

If your XML is in a file, then Document document will be instantiated like this:

Document document = builder.parse(new File("file.xml"));

The document.getDocumentElement() returns you the node that is the document element of the document (in your case <config>).

Once you have a rootElement, you can access the element's attribute (by calling rootElement.getAttribute() method), etc. For more methods on java's org.w3c.dom.Element

More info on java DocumentBuilder & DocumentBuilderFactory. Bear in mind, the example provided creates a XML DOM tree so if you have a huge XML data, the tree can be huge.


Update Here's an example to get "value" of element <requestqueue>

protected String getString(String tagName, Element element) {
        NodeList list = element.getElementsByTagName(tagName);
        if (list != null && list.getLength() > 0) {
            NodeList subList = list.item(0).getChildNodes();

            if (subList != null && subList.getLength() > 0) {
                return subList.item(0).getNodeValue();
            }
        }

        return null;
    }

You can effectively call it as,

String requestQueueName = getString("requestqueue", element);
Community
  • 1
  • 1
Buhake Sindi
  • 87,898
  • 29
  • 167
  • 228
  • 5
    Why not use the built in Java SE XPath library? http://stackoverflow.com/questions/4076910/how-to-retrieve-element-value-of-xml-using-java/4077986#4077986 – bdoughan Nov 03 '10 at 18:06
  • @Blaise Doughan, you could. I just used DOM to support legacy java that are still active out there. – Buhake Sindi Nov 03 '10 at 18:23
  • 4
    Fair enough, if someone is still on JDK 1.4 then your approach is reasonable. If they are on 1.5 or later then the javax.xml.xpath library is much easier. I hate to see people doing things the hard way when a better way exists. – bdoughan Nov 03 '10 at 18:43
  • 1
    @Blaise Doughan, you will be surprised at how many companies (most especially banks) still run JDK 1.4. – Buhake Sindi Nov 03 '10 at 18:45
  • 1
    Agreed there are developers using JDK 1.4, and that your solution is appropriate to JDK 1.4. If, however they are using JDK 1.5 or above the javax.xml.xpath library is more appropriate. There are many developers with JDK 1.5 and 1.6 as baselines. – bdoughan Nov 03 '10 at 19:28
38

In case you just need one (first) value to retrieve from xml:

public static String getTagValue(String xml, String tagName){
    return xml.split("<"+tagName+">")[1].split("</"+tagName+">")[0];
}

In case you want to parse whole xml document use JSoup:

Document doc = Jsoup.parse(xml, "", Parser.xmlParser());
for (Element e : doc.select("Request")) {
    System.out.println(e);
}
Yuriy N.
  • 4,936
  • 2
  • 38
  • 31
29

If you are just looking to get a single value from the XML you may want to use Java's XPath library. For an example see my answer to a previous question:

It would look something like:

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathFactory;

import org.w3c.dom.Document;
import org.w3c.dom.NodeList;

public class Demo {

    public static void main(String[] args) {
        DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance();
        try {
            DocumentBuilder builder = domFactory.newDocumentBuilder();
            Document dDoc = builder.parse("E:/test.xml");

            XPath xPath = XPathFactory.newInstance().newXPath();
            Node node = (Node) xPath.evaluate("/Request/@name", dDoc, XPathConstants.NODE);
            System.out.println(node.getNodeValue());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}
Community
  • 1
  • 1
bdoughan
  • 147,609
  • 23
  • 300
  • 400
5

There are a number of different ways to do this. You might want to check out XStream or JAXB. There are tutorials and the examples.

posdef
  • 6,498
  • 11
  • 46
  • 94
  • @sam: And you probably want to check this SO question as well, http://stackoverflow.com/questions/1558087/xstream-or-simple. – Adeel Ansari Nov 02 '10 at 10:55
4

If the XML is well formed then you can convert it to Document. By using the XPath you can get the XML Elements.

String xml = "<stackusers><name>Yash</name><age>30</age></stackusers>";

Form XML-String Create Document and find the elements using its XML-Path.

Document doc = getDocument(xml, true);

    public static Document getDocument(String xmlData, boolean isXMLData) throws Exception {
        DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
        dbFactory.setNamespaceAware(true);
        dbFactory.setIgnoringComments(true);
        DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
        Document doc;
        if (isXMLData) {
            InputSource ips = new org.xml.sax.InputSource(new StringReader(xmlData));
            doc = dBuilder.parse(ips);
        } else {
            doc = dBuilder.parse( new File(xmlData) );
        }
        return doc;
    }

Use org.apache.xpath.XPathAPI to get Node or NodeList.

System.out.println("XPathAPI:"+getNodeValue(doc, "/stackusers/age/text()"));

NodeList nodeList = getNodeList(doc, "/stackusers");
System.out.println("XPathAPI NodeList:"+ getXmlContentAsString(nodeList));
System.out.println("XPathAPI NodeList:"+ getXmlContentAsString(nodeList.item(0)));

    public static String getNodeValue(Document doc, String xpathExpression) throws Exception {
        Node node = org.apache.xpath.XPathAPI.selectSingleNode(doc, xpathExpression);
        String nodeValue = node.getNodeValue();
        return nodeValue;
    }
    public static NodeList getNodeList(Document doc, String xpathExpression) throws Exception {
        NodeList result = org.apache.xpath.XPathAPI.selectNodeList(doc, xpathExpression);
        return result;
    }

Using javax.xml.xpath.XPathFactory

System.out.println("javax.xml.xpath.XPathFactory:"+getXPathFactoryValue(doc, "/stackusers/age"));

    static XPath xpath = javax.xml.xpath.XPathFactory.newInstance().newXPath();
    public static String getXPathFactoryValue(Document doc, String xpathExpression) throws XPathExpressionException, TransformerException, IOException {
        Node node = (Node) xpath.evaluate(xpathExpression, doc, XPathConstants.NODE);
        String nodeStr = getXmlContentAsString(node);
        return nodeStr;
    }

Using Document Element.

System.out.println("DocumentElementText:"+getDocumentElementText(doc, "age"));

    public static String getDocumentElementText(Document doc, String elementName) {
        return doc.getElementsByTagName(elementName).item(0).getTextContent();
    }

Get value in between two strings.

String nodeVlaue = org.apache.commons.lang.StringUtils.substringBetween(xml, "<age>", "</age>");
System.out.println("StringUtils.substringBetween():"+nodeVlaue);

Full Example:

public static void main(String[] args) throws Exception {
    String xml = "<stackusers><name>Yash</name><age>30</age></stackusers>";
    Document doc = getDocument(xml, true);
    
    String nodeVlaue = org.apache.commons.lang.StringUtils.substringBetween(xml, "<age>", "</age>");
    System.out.println("StringUtils.substringBetween():"+nodeVlaue);
    
    System.out.println("DocumentElementText:"+getDocumentElementText(doc, "age"));
    System.out.println("javax.xml.xpath.XPathFactory:"+getXPathFactoryValue(doc, "/stackusers/age"));
    
    System.out.println("XPathAPI:"+getNodeValue(doc, "/stackusers/age/text()"));
    NodeList nodeList = getNodeList(doc, "/stackusers");
    System.out.println("XPathAPI NodeList:"+ getXmlContentAsString(nodeList));
    System.out.println("XPathAPI NodeList:"+ getXmlContentAsString(nodeList.item(0)));
}
public static String getXmlContentAsString(Node node) throws TransformerException, IOException {
    StringBuilder stringBuilder = new StringBuilder();
    NodeList childNodes = node.getChildNodes();
    int length = childNodes.getLength();
    for (int i = 0; i < length; i++) {
        stringBuilder.append( toString(childNodes.item(i), true) );
    }
    return stringBuilder.toString();
}

OutPut:

StringUtils.substringBetween():30
DocumentElementText:30
javax.xml.xpath.XPathFactory:30
XPathAPI:30
XPathAPI NodeList:<stackusers>
   <name>Yash</name>
   <age>30</age>
</stackusers>
XPathAPI NodeList:<name>Yash</name><age>30</age>
Yash
  • 9,250
  • 2
  • 69
  • 74
1

There are two general ways of doing that. You will either create a Domain Object Model of that XML file, take a look at this

and the second choice is using event driven parsing, which is an alternative to DOM xml representation. Imho you can find the best overall comparison of these two basic techniques here. Of course there are much more to know about processing xml, for instance if you are given XML schema definition (XSD), you could use JAXB.

lisak
  • 21,611
  • 40
  • 152
  • 243
1

There are various APIs available to read/write XML files through Java. I would refer using StaX

Also This can be useful - Java XML APIs

Community
  • 1
  • 1
Vishal
  • 2,711
  • 7
  • 33
  • 42
1

Since you are using this for configuration, your best bet is apache commons-configuration. For simple files it's way easier to use than "raw" XML parsers.

See the XML how-to

Bozho
  • 588,226
  • 146
  • 1,060
  • 1,140
1

You can make a class which extends org.xml.sax.helpers.DefaultHandler and call

start_<tag_name>(Attributes attrs);

and

end_<tag_name>();

For it is:

start_request_queue(attrs);

etc.

And then extends that class and implement xml configuration file parsers you want. Example:

  ...
  public void startElement(String uri, String name, String qname,
                           org.xml.sax.Attributes attrs) 
                  throws org.xml.sax.SAXException {
    Class[] args = new Class[2];
    args[0] = uri.getClass();
    args[1] = org.xml.sax.Attributes.class;
    try {
      String mname = name.replace("-", "");
      java.lang.reflect.Method m = 
            getClass().getDeclaredMethod("start" + mname, args);
      m.invoke(this, new Object[] { uri, (org.xml.sax.Attributes)attrs }); 
    }
catch (IllegalAccessException e) { throw new RuntimeException(e); }
catch (NoSuchMethodException e) { throw new RuntimeException(e); }
catch (java.lang.reflect.InvocationTargetException e) { org.xml.sax.SAXException se = new org.xml.sax.SAXException(e.getTargetException()); se.setStackTrace(e.getTargetException().getStackTrace()); }

and in a particular configuration parser:

   public void start_Request(String uri, org.xml.sax.Attributes attrs) {
     // make sure to read attributes correctly
     System.err.println("Request, name="+ attrs.getValue(0);
   }
khachik
  • 28,112
  • 9
  • 59
  • 94