Given the following XML (basic.xml):
<rdr> <details> <detail> <name>version</name> <value>15.0</value> </detail> <detail> <name>resolution</name> <value>1080X1920</value> </detail> </details> </rdr>
I want to get the name and versions, so I have the following code. This is not very neat, but I created it for illustrative purposes, but the code works completely:
import java.io.FileInputStream; import java.io.IOException; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import javax.xml.xpath.XPath; import javax.xml.xpath.XPathConstants; import javax.xml.xpath.XPathExpressionException; import javax.xml.xpath.XPathFactory; import org.w3c.dom.Document; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.xml.sax.SAXException; public class Example { private static XPath factoryXpath = null; public static void main(String[] args) throws ParserConfigurationException, SAXException, IOException, XPathExpressionException { FileInputStream fin = new FileInputStream("basic.xml"); DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); DocumentBuilder builder = factory.newDocumentBuilder(); Document document = builder.parse(fin); XPathFactory xPathFactory = XPathFactory.newInstance(); factoryXpath = xPathFactory.newXPath(); printDetails(document); } public static void printDetails(Node node) throws XPathExpressionException { NodeList nodes = (NodeList) factoryXpath.evaluate("//detail", node, XPathConstants.NODESET); printNameAndValue(nodes.item(0)); printNameAndValue(nodes.item(1)); } public static void printNameAndValue(Node node) throws XPathExpressionException { System.out.println("Name=" + (String) factoryXpath.evaluate("//name", node, XPathConstants.STRING)); System.out.println("Value=" + (String) factoryXpath.evaluate("//value", node, XPathConstants.STRING)); } }
Outputs the following:
Name=version Value=15.0 Name=version Value=15.0
Why does it print the same name and value both times?
If I clone node first, so printNameAndValue now looks like this:
public static void printNameAndValue(Node node) throws XPathExpressionException { Node clonedNode = node.cloneNode(true); System.out.println("Name=" + (String) factoryXpath.evaluate("//name", clonedNode, XPathConstants.STRING)); System.out.println("Value=" + (String) factoryXpath.evaluate("//value", clonedNode, XPathConstants.STRING)); }
I get the following output:
Name=version Value=15.0 Name=resolution Value=1080X1920
Why does a cloned node act differently?
I deleted the cloned node and returned to the original example when it wasnβt working, and added the method described here https://stackoverflow.com/a/2128167/2208 , but with this, accepting the node instead of the document in its attributes. This produces the following result:
<?xml version="1.0" encoding="UTF-8"?><detail> <name>version</name> <value>15.0</value> </detail> Name=version Value=15.0 <?xml version="1.0" encoding="UTF-8"?><detail> <name>resolution</name> <value>1080X1920</value> </detail> Name=version Value=15.0
From this it is clear that node is the one we expect; but it applies XPath to the first node, or perhaps to the original document. I am fine with cloning a node and using this, but I would really like to know why this is happening.