2

Can somebody find what is wrong with this code. It always returns empty string no matter whatever XPath I choose

DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance();
domFactory.setNamespaceAware(true);
DocumentBuilder builder = domFactory.newDocumentBuilder();
Document doc = builder.parse("chart.xml");
XPath xpath = XPathFactory.newInstance().newXPath();
String str = (String) xpath.evaluate("/row[@id='1']", doc.getDocumentElement(),    XPathConstants.STRING);
System.out.println("xml string is"+str);

My chart.xml is

<?xml version="1.0" encoding="iso-8859-1"?>
 <chart>
  <row id="1">
    <Select numofobjects="0" id="1000" index="1">
      <Table alias="ConvertDetails" name="ConvertDetails"/>
   </Select>
 </row>
 <row id="2">
   <Select numofobjects="0" id="2000" index="2">
      <Table alias="ConvertDetails" name="ConvertDetails"/>
  </Select>
 </row>
</chart>

My expected output is

<Select numofobjects="0" id="1000" index="1">
      <Table alias="ConvertDetails" name="ConvertDetails"/>
   </Select>
Sankar
  • 369
  • 4
  • 17

3 Answers3

2

As Martin points out, you need to select a node, and not the string value of it:

DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance();
domFactory.setNamespaceAware(true);
DocumentBuilder builder = domFactory.newDocumentBuilder();
Document doc = builder.parse("chart.xml");
XPath xpath = XPathFactory.newInstance().newXPath();
Node n = (Node) xpath.evaluate("row[@id='1']", doc.getDocumentElement(), 
                               XPathConstants.NODE);

Then you can use the following serialization helper method (borrowed from Get a node's inner XML as String in Java DOM):

public static String innerXml(Node node) {
    DOMImplementationLS lsImpl = (DOMImplementationLS)node.getOwnerDocument()
                                                          .getImplementation()
                                                          .getFeature("LS", "3.0");
    LSSerializer lsSerializer = lsImpl.createLSSerializer();
    lsSerializer.getDomConfig().setParameter("xml-declaration", false);
    NodeList childNodes = node.getChildNodes();
    StringBuilder sb = new StringBuilder();
    for (int i = 0; i < childNodes.getLength(); i++) {
       sb.append(lsSerializer.writeToString(childNodes.item(i)));
    }
    return sb.toString(); 
}

Like this:

String xmlStr = "";
if (n != null) {
    xmlStr = innerXml(node);
}
Community
  • 1
  • 1
JLRishe
  • 99,490
  • 19
  • 131
  • 169
  • 1
    JLRishe I got this exception while excuting the above code "org.w3c.dom.ls.LSException: unable-to-serialize-node: unable-to-serialize-node: The node could not be serialized." – Sankar Dec 11 '14 at 13:33
  • @Sankar Hm, I'm not sure what would be causing that. Which line is producing the error? – JLRishe Dec 11 '14 at 17:27
  • 1
    sb.append(lsSerializer.writeToString(childNodes.item(i))); – Sankar Dec 12 '14 at 05:14
0

If you want to select a node then don't use XPathConstants.STRING as that takes the string contents of the selected node and all your elements are empty. You would need to select a node or node-set and make sure you serialize the node if you want its markup.

Martin Honnen
  • 160,499
  • 6
  • 90
  • 110
  • I tried both, but it always returns null only. Please correct me If i am wrong. code :- Node nodes = (Node) xpath.evaluate("/row[@id='1']", doc.getDocumentElement(), XPathConstants.NODE); – Sankar Dec 11 '14 at 13:13
  • Well the path is also wrong, to make sense to select relative to the document element (which is the `chart` element) use `row[@id=1]`. – Martin Honnen Dec 11 '14 at 13:18
0

Using @JLRishe's code works perfect (+1).

The problem is with your XML document. You close the <Select> tags wrong (with </SelectOne> \ </SelectTwo>).

Try running this code on the following XML:

Code:

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.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.ls.DOMImplementationLS;
import org.w3c.dom.ls.LSSerializer;

public class XMLSerializer {
    public static void main(String[] args) {
        try {
            DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance();
            domFactory.setNamespaceAware(true);
            DocumentBuilder builder = domFactory.newDocumentBuilder();
            Document doc = builder.parse("chart.xml");
            XPath xpath = XPathFactory.newInstance().newXPath();
            Node n = (Node) xpath.evaluate("row[@id='1']", doc.getDocumentElement(), 
                                           XPathConstants.NODE);

            String xmlStr = "";
            if (n != null) {
                xmlStr = innerXml(n);
                System.out.println("xml string is"+xmlStr);
            }

        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    public static String innerXml(Node node) {
        DOMImplementationLS lsImpl = (DOMImplementationLS)node.getOwnerDocument()
                                                              .getImplementation()
                                                              .getFeature("LS", "3.0");
        LSSerializer lsSerializer = lsImpl.createLSSerializer();
        lsSerializer.getDomConfig().setParameter("xml-declaration", false);
        NodeList childNodes = node.getChildNodes();
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < childNodes.getLength(); i++) {
           sb.append(lsSerializer.writeToString(childNodes.item(i)));
        }
        return sb.toString(); 
    }
}

XML:

<?xml version="1.0" encoding="iso-8859-1"?>
<chart>
  <row id="1">
    <Select numofobjects="0" id="1000" index="1">
      <Table alias="ConvertDetails" name="ConvertDetails"/>
    </Select>
  </row>
  <row id="2">
    <Select numofobjects="0" id="2000" index="2">
      <Table alias="ConvertDetails" name="ConvertDetails"/>
    </Select>
  </row>
</chart>
Elist
  • 5,313
  • 3
  • 35
  • 73
  • It works fine in a standalone program. If i use this in my apache server, it will throw org.w3c.dom.ls.LSException exception. – Sankar Dec 12 '14 at 05:35
  • Are sure your XML's are well formed? You can validate the document befor processing it. – Elist Dec 12 '14 at 08:19