我有以下程序:
package xpath;
import java.io.StringReader;
import java.util.List;
import org.dom4j.Document;
import org.dom4j.Node;
import org.dom4j.io.SAXReader;
public class TryXPath
{
public static void say(String message) { System.out.println(message); }
public static String mainDocumentXML
= "<GetAvailableProductsResponse xmlns=\"http://api.onecommunications.com/pricing_availability/\">" +
" <GetAvailableProductsResult>" +
" <Products>" +
" <Product>" +
" <ProductID>101236004</ProductID>" +
" <BaseProductName>Widget1</BaseProductName>" +
" </Product>" +
" <Product>" +
" <ProductID>101236005</ProductID>" +
" <BaseProductName>Widget2</BaseProductName>" +
" </Product>" +
" <Product>" +
" <ProductID>101236006</ProductID>" +
" <BaseProductName>Widget3</BaseProductName>" +
" </Product>" +
" </Products>" +
" </GetAvailableProductsResult>" +
"</GetAvailableProductsResponse>";
public static void main(String[] args)
{
String PRODUCTS_NODE_PATH = "/*[name()='GetAvailableProductsResponse']/*[name()='GetAvailableProductsResult']/*[name()='Products']";
String PRODUCTS_PATH = "/*[name()='Product']";
try
{
org.dom4j.io.SAXReader reader = new SAXReader();
Document document = reader.read(new StringReader(mainDocumentXML));
Node root = document.selectSingleNode(PRODUCTS_NODE_PATH);
if (root == null)
{
say("No root");
}
else
{
List<Node> productsNodeList = root.selectNodes(PRODUCTS_NODE_PATH + PRODUCTS_PATH);
say("products node list size=" + productsNodeList.size());
for (Node node : productsNodeList)
{
say("node: " + node.asXML());
say("name: " + node.getName());
say("id: " + node.selectSingleNode("//*[local-name()='ProductID']").getText());
}
}
}
catch (Exception e) { e.printStackTrace(); }
}
}
它解析给定的XML;一部分产生一个3个产品节点的列表,然后我想要做的是访问每个节点内的项目。但是,我使用的ProductID的XPath表达式不正确(&#34; // * [local-name()=&#39; ProductID&#39;]&#34;);它显然搜索主文档,而不是调用selectSingleNode()
方法的节点。
该计划的输出:
products node list size=3
node: <Product xmlns="http://api.onecommunications.com/pricing_availability/"> <ProductID>101236004</ProductID> <BaseProductName>Widget1</BaseProductName> </Product>
name: Product
id: 101236004
node: <Product xmlns="http://api.onecommunications.com/pricing_availability/"> <ProductID>101236005</ProductID> <BaseProductName>Widget2</BaseProductName> </Product>
name: Product
id: 101236004
node: <Product xmlns="http://api.onecommunications.com/pricing_availability/"> <ProductID>101236006</ProductID> <BaseProductName>Widget3</BaseProductName> </Product>
name: Product
id: 101236004
请注意&#34; id&#34;的所有值来自第一个节点,而不是被调用selectSingleNode()
的节点的ProductID值。
我已经尝试过各种各样的组合&#34;。&#34;,&#34; /&#34;,no&#34; /&#34;,&#34;: :&#34;等等,我似乎无法找到将在列表中的单个Product节点内返回ProductID节点的XPath表达式。我该怎么做?
答案 0 :(得分:0)
基本问题是字符串“// * [local-name()='ProductID']”)中的'//'将找到所有ProductID,无论它们在文档中的位置。当与selectSingleNode()方法一起使用时,您将始终获得该集合中的第一个。
你真正想做的是在'ProductID'路径上的selectNodes()并迭代这些。您甚至可以通过执行一些相对调用来获取与“ProductID”关联的关联“BaseProductName”(参见下文)。
public static void main(String[] args){
String PRODUCTS_NODE_PATH = "/*[name()='GetAvailableProductsResponse']/*[name()='GetAvailableProductsResult']/*[name()='Products']";
try {
org.dom4j.io.SAXReader reader = new SAXReader();
Document document = reader.read(new StringReader(mainDocumentXML));
Node root = document.selectSingleNode(PRODUCTS_NODE_PATH);
if (root == null) {
say("No root");
} else {
// [JIM] Get all the ProductID nodes
List<Node> productsNodeList = root.selectNodes("./*[local-name()='Product']/*[local-name()='ProductID']");
// [JIM] Now iterate through and pull out the values
say("products node list size=" + productsNodeList.size());
for (Node node : productsNodeList) {
say(node.getText());
// [JIM] Get the associated BaseProductName relative to the current ProductID
say(node.getParent().selectSingleNode("./*[local-name()='BaseProductName']").getText());
}
}
} catch (Exception e) {
e.printStackTrace();
}
}