Запуск XPath для дочернего node
Я пытаюсь выполнить поиск по xpath на узлах, возвращаемых путем поиска по xpath, но он не работает, как я ожидал. XPaths, выполняемые на дочерних узлах документа, как представляется, выполняются против hthe root node документа (в примере, тег инвентаря.) вместо корня предоставленного node.
Я что-то упустил? Я новичок в XPath.
Кроме того, пожалуйста, не отвечайте "just do//book [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>
Ответы
Ответ 1
/foo
будет выбирать на основе корня node, игнорируя контекст, который вы оцениваете по пути xpath. foo
(без косой черты) - это то, что вы хотите; который выбирает исходящий из текущего node.
https://www.w3schools.com/xml/xpath_syntax.asp дает немного больше информации.
Ответ 2
в Xpath, "." (Dot) представляет текущий документ.
Итак, напишите строку XPATH после ".". (Dot).
ex:
"./title"
или
".//title"
Что бы вы ни пожелали....
удаление косой черты работает только в том случае, если это дочерний элемент node.
Что делать, если вы хотите использовать функцию//(где бы вы ни находились в текущем документе)?
Итак, используйте точку (.)
Спасибо за вышеупомянутые ответы тоже:).
Ответ 3
Просто возьмите слэш из ваших подзапросов, и все будет в порядке. Итак, вы получаете свои книги через "//book"
, а затем оттуда просто "title"
, "inventory"
и т.д., Чтобы получить дочерние биты.
Ответ 4
На самом деле это странно в реализации Java: Node, извлеченный из документа, все еще ссылается на родительский документ (см. Node.getOwnerDocument()
), а xpath использует это для поиска корня.
Другие упомянули способ изменения xpath, чтобы фактически не начинать с корня, удаляя косые черты.
У меня была аналогичная проблема, но я хотел, чтобы xpath обрабатывал как корневые документы, так и дочерние узлы (с xpath вроде /title
). Решением было клонирование Node: Node.cloneNode(true)
. Обратите внимание на параметр true
, который заставляет Node отключить родительский документ.
... В конце концов, это сильно вредит производительности и имеет отдельные xpaths для обработки Node, а Document предпочтительнее.