我目前在java中遇到了xpath表达式问题。 我想获得一个shopNames列表!
我得到了以下XML;
<?xml version="1.0" encoding="UTF-8"?>
<w:shops xmlns:w="namespace">
<w:shop>
<w:shopID>1</w:shopID>
<w:shopName>ShopName</w:shopName>
<w:shopURL>ShopUrl</w:shopURL>
</w:shop>
<w:shop>
<w:shopID>2</w:shopID>
<w:shopName>ShopNames</w:shopName>
<w:shopURL>ShopUrl</w:shopURL>
</w:shop>
</w:shops>
我正在将文档中的内容添加到函数中:
List<String> getShops(Document d)
throws Exception
{
List<String> shopnames = new ArrayList<String>();
XPath xpath = XPathFactory.newInstance().newXPath();
XPathExpression expr = xpath.compile("/descendant::w:shop/descendant::w:shopName");
NodeList nodes = (NodeList) expr.evaluate(d, XPathConstants.NODESET);
for(int x=0; x<nodes.getLength(); x++)
{
shopnames.add("" + nodes.item(x).getNodeValue());
}
return shopnames;
}
然而问题是它只返回一个空列表,我怀疑它是我的xpath表达式,但我不确定。
有人在这里看到这个问题吗?
答案 0 :(得分:4)
根元素不是shop
,而是shops
。我想,你必须编译这个表达式:
xpath.compile("/descendant::w:shops/descendant::w:shop/descendant::w:shopName");
您可能必须设置名称空间上下文:
xpath.setNamespaceContext(new NamespaceContext() {
public String getNamespaceURI(String prefix) {
if (prefix.equals("w")) return "namespace";
else return XMLConstants.NULL_NS_URI;
}
public String getPrefix(String namespace) {
if (namespace.equals("namespace")) return "w";
else return null;
}
public Iterator getPrefixes(String namespace) {return null;}
});
并解析,以便文档知道名称空间
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setNamespaceAware(true); // <----
DocumentBuilder db = dbf.newDocumentBuilder();
Document xmlDom = db.parse("./shops.xml");
答案 1 :(得分:2)
这个也有效://w:shopName/text()
不是“选择性的”,但我认为它更具可读性。并返回一个字符串列表,而不是一个节点列表,这些节点可能更好或不更好,具体取决于您的需要。
答案 2 :(得分:2)
您是否需要在XPath实例上设置NamespaceContext?我认为你必须这样才能确认你的'w'ns。
答案 3 :(得分:1)
您不必具体说明nscontext,您的XPath expr会更长一些,但会说一切:
/*[namespace-uri()='namespace' and local-name()='shops']/*[namespace-uri()='namespace' and local-name()='shop']/*[namespace-uri()='namespace' and local-name()='shopName']
所以在Java中:
XPathFactory factory = XPathFactory.newInstance();
XPath xp = factory.newXPath();
String xpath =
"/*[namespace-uri()='namespace' and local-name()='shops']/*[namespace-uri()='namespace' and local-name()='shop']/*[namespace-uri()='namespace' and local-name()='shopName']";
XPathExpression expr = xp.compile(xpath);
NodeList nlist = (NodeList) expr.evaluate(e, XPathConstants.NODESET);
ArrayList<String> shopNamesList = new ArrayList<String>();
for (int i = 0; i < nlist.getLength(); i++) {
shopNamesList.add(((Element) nlist.item(i)).getNodeValue());
}
这应该有效。 此致