Запуск XPath на дочернем узле - PullRequest
48 голосов
/ 11 апреля 2010

Я пытаюсь выполнить поиск xpath на узлах, возвращенных поиском xpath, но, похоже, он не работает так, как я ожидал. документ (в примере тег инвентаризации.) вместо корня предоставленного узла.

Я что-то здесь упускаю? Я новичок в XPath.

Также, пожалуйста, не отвечайте "просто сделай // книгу [author = 'Neal Stephenson' / title" ". У меня есть законный вариант использования, и это упрощенный пример.

Фрагмент кода

DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance();
domFactory.setNamespaceAware(true);
DocumentBuilder builder = domFactory.newDocumentBuilder();
Document doc = builder.parse("src/main/java/books.xml");

XPathFactory factory = XPathFactory.newInstance();
XPath xpath = factory.newXPath();

Node book = (Node) xpath.evaluate("//book[author='Neal Stephenson']", doc, XPathConstants.NODE);
Node title = (Node) xpath.evaluate("/title", book, XPathConstants.NODE); // I get null here.
Node inventory = (Node) xpath.evaluate("/inventory", book, XPathConstants.NODE); // this returns a node.

book.xml

<inventory>
<book year="2000">
    <title>Snow Crash</title>
    <author>Neal Stephenson</author>
    <publisher>Spectra</publisher>
    <isbn>0553380958</isbn>
    <price>14.95</price>
</book>

<book year="2005">
    <title>Burning Tower</title>
    <author>Larry Niven</author>
    <author>Jerry Pournelle</author>
    <publisher>Pocket</publisher>
    <isbn>0743416910</isbn>
    <price>5.99</price>
</book>

<book year="1995">
    <title>Zodiac</title>
    <author>Neal Stephenson</author>
    <publisher>Spectra</publisher>
    <isbn>0553573862</isbn>
    <price>7.50</price>
</book>

<!-- more books... -->

</inventory>

Ответы [ 4 ]

48 голосов
/ 11 апреля 2010

/foo будет выбран на основе корневого узла, игнорируя контекст, с которым вы оцениваете xpath.foo (без косой черты) - это то, что вы хотите;это выбирает на основе текущего узла.

https://www.w3schools.com/xml/xpath_syntax.asp дает немного больше информации.

25 голосов
/ 06 апреля 2013

в Xpath, "." (Точка) представляет текущий документ. Итак, напишите вашу строку XPATH после "." (Точка).

например:

"./title"

или

".//title"

Как хочешь ....

удаление косой черты работает, только если она является дочерней по отношению к узлу. Что если вы хотите использовать функциональность // (где бы в текущем документе)?

Итак, используйте точку (.)

Большое спасибо и за ответы выше :).

7 голосов
/ 11 апреля 2010

Просто уберите начальный слеш из ваших подзапросов, и все будет в порядке. Таким образом, вы получаете свои книги через "//book", а затем оттуда просто "title", "inventory" и т. Д., Чтобы получить дочерние биты.

3 голосов
/ 05 октября 2012

Что на самом деле странно в реализации Java, так это то, что узел, извлеченный из документа, все еще ссылается на родительский документ (см. Node.getOwnerDocument()), и xpath использует его для поиска корня.

Другие упоминали способ изменить xpath, чтобы фактически не начинался с корня путем удаления косой черты.

У меня была похожая проблема, но я хотел, чтобы xpath обрабатывал как корневые документы, так и дочерние узлы (с xpath вроде /title). Решением было клон узел: Node.cloneNode(true). Обратите внимание на параметр true, который заставляет узел стряхивать свой родительский документ.

... В конце концов, это слишком сильно снижает производительность, поэтому предпочтительнее было иметь отдельные пути xpath для обработки Node и Document.

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