Проблемы с xpath в Java - PullRequest
       1

Проблемы с xpath в Java

2 голосов
/ 17 февраля 2011

У меня сейчас проблема с выражениями xpath в java.Я пытаюсь получить список 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 ]

4 голосов
/ 17 февраля 2011

Корневым элементом является не 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");
2 голосов
/ 17 февраля 2011

Вам не нужно устанавливать NamespaceContext в вашем экземпляре XPath? Я думаю, что вам нужно, чтобы ваши 'w' ns были распознаны.

2 голосов
/ 17 февраля 2011

Это тоже работает: //w:shopName/text() не так "избирательно", но я думаю, что это более читабельно.И возвращает список строк, а не список узлов, который может быть лучше или нет, в зависимости от того, что вам нужно.

1 голос
/ 22 февраля 2011

Вам не нужно указывать 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());
        }

Это должно работать. Привет

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...