給出下面的XML(basic.xml):爲什麼javax.xml.xpath.XPath與克隆節點的行爲不同?
<rdr>
<details>
<detail>
<name>version</name>
<value>15.0</value>
</detail>
<detail>
<name>resolution</name>
<value>1080X1920</value>
</detail>
</details>
</rdr>
我想要得到的名稱和版本了,所以我有下面的代碼。這是不是很整齊,但我創造了這個用於說明目的,但代碼不會完全功能:
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));
}
}
此輸出以下:
Name=version
Value=15.0
Name=version
Value=15.0
爲什麼它輸出相同的名稱和價值兩次?
如果我第一次克隆的節點上,使printNameAndValue現在看起來是這樣的:
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));
}
我得到以下輸出:
Name=version
Value=15.0
Name=resolution
Value=1080X1920
爲什麼克隆節點的行爲不同?
我刪除了克隆的節點,並恢復到原來的例子,它不起作用,並添加了這裏描述的方法https://stackoverflow.com/a/2325407/211560,但它的屬性採用節點而不是文檔。這打印出以下結果:
<?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
由此可見,節點是我們所期望的節點;但它將XPath應用於第一個節點,或者也可能應用於原始文檔。我很喜歡克隆一個節點並使用它,但我真的很想知道爲什麼會發生這種情況。
謝謝你。我假設一個節點會丟棄它所屬的文檔;但這確實解釋了原因。 – Arthur