Получите Xpath из org.w3c.dom.Node - PullRequest
22 голосов
/ 18 февраля 2011

Могу ли я получить полный xpath из org.w3c.dom.Node?

Скажем, в данный момент узел указывает на то, где находится середина XML-документа.Я хотел бы извлечь xpath для этого элемента.

Выходной xpath, который я ищу, это //parent/child1/chiild2/child3/node.Родитель узла xpath.Просто игнорируйте xpath, которые имеют выражения и указывают на один и тот же узел.

Ответы [ 6 ]

13 голосов
/ 18 февраля 2011

Не существует универсального метода для получения XPath, главным образом потому, что нет ни одного универсального XPath, который идентифицировал бы конкретный узел в документе. В некоторых схемах узлы будут однозначно идентифицироваться атрибутом (id и name, вероятно, являются наиболее распространенными атрибутами.) В других, имени каждого элемента (то есть тега) достаточно, чтобы однозначно идентифицировать узел , В некоторых (маловероятных, но возможных) случаях не существует ни одного уникального имени или атрибута, который перенес бы вас в определенный узел, и поэтому вам нужно было бы использовать количество элементов (получить n-й дочерний элемент m-го дочернего элемента. ..).

EDIT : В большинстве случаев несложно создать зависимую от схемы функцию для сборки XPath для данного узла. Например, предположим, что у вас есть документ, в котором каждый узел уникально идентифицируется атрибутом id, и вы не используете пространства имен. Тогда ( Я думаю ) следующая псевдо-Java будет работать для возврата XPath, основанного на этих атрибутах. ( Предупреждение: я не проверял это. )

String getXPath(Node node)
{
    Node parent = node.getParent();
    if (parent == null) {
        return "/" + node.getTagName();
    }
    return getXPath(parent) + "/" + "[@id='" + node.getAttribute("id") + "']";
}
12 голосов
/ 20 января 2012

Я работаю в компании, стоящей за jOOX , библиотекой, которая предоставляет множество полезных расширений для стандартного API DOM Java, имитируя jquery API .С помощью jOOX вы можете получить XPath любого элемента, подобного следующему:

String path = $(element).xpath();

Приведенный выше путь будет примерно таким:

/document[1]/library[2]/books[3]/book[1]
7 голосов
/ 05 февраля 2016

Для меня этот работал лучше всего (с использованием элементов org.w3c.dom):

String getXPath(Node node)
{
    Node parent = node.getParentNode();
    if (parent == null)
    {
        return "";
    }
    return getXPath(parent) + "/" + node.getNodeName();
}
7 голосов
/ 26 октября 2012

Я взял этот код из сообщения Миккеля Флиндта и изменил его, чтобы он мог работать для узла атрибутов.

3 голосов
/ 19 февраля 2011

Некоторые IDE, специализирующиеся на XML, сделают это за вас.

Вот самые известные

  1. Кислородные
  2. Stylus Studio
  3. XMLSpy

Например, в oXygen вы можете щелкнуть правой кнопкой мыши на элементе элемента XML-документа, и в контекстном меню появится опция «Копировать Xpath».

Существует также ряд дополнений Firefox (например, XPather , которые с радостью выполнят эту работу за вас. Для Xpather вы просто нажимаете на часть веб-страницы и выбираете в контекстном меню. меню «показать в XPather» и все готово.

Но, как указал Дэн в своем ответе, выражение XPath будет иметь ограниченное применение. Например, он не будет содержать предикатов. Скорее это будет выглядеть так.

/root/nodeB[2]/subnodeX[2]

Для документов типа

<root>
   <nodeA>stuff</nodeA>
   <nodeB>more stuff</nodeB>
   <nodeB cond="thisOne">
       <subnodeX>useless stuff</subnodeX>
       <subnodeX id="MyCondition">THE STUFF YOU WANT</subnodeX>
       <subnodeX>more useless stuff</subnodeX>
   </nodeB>
</root>

Инструменты, которые я перечислил, будут не генерировать

/root/nodeB[@cond='thisOne']/subnodeX[@id='MyCondition']

Например, для html-страницы вы получите довольно бесполезное выражение:

/html/body/div[6]/p[3]

И этого следовало ожидать. Если бы им пришлось генерировать предикаты, как бы они узнали, какое условие имеет отношение? Есть миллионы возможностей.

0 голосов
/ 13 мая 2013

Примерно так получится простой xpath:

public String getXPath(Node node) {
    return getXPath(node, "");
}

public String getXPath(Node node, String xpath) {
    if (node == null) {
        return "";
    }
    String elementName = "";
    if (node instanceof Element) {
        elementName = ((Element) node).getLocalName();
    }
    Node parent = node.getParentNode();
    if (parent == null) {
        return xpath;
    }
    return getXPath(parent, "/" + elementName + xpath);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...