java中xpath的问题

时间:2011-02-17 10:21:37

标签: java xml dom xpath

我目前在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表达式,但我不确定。

有人在这里看到这个问题吗?

4 个答案:

答案 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());
        }

这应该有效。 此致