从org.w3c.dom.Node获取Xpath

sri*_*apa 23 java xml dom

我可以从org.w3c.dom.Node获取完整的xpath吗?

说当前节点指向xml文档中间的某些位置.我想提取该元素的xpath.

我正在寻找的输出xpath是//parent/child1/chiild2/child3/node.节点xpath的父节点.只需忽略具有表达式并指向同一节点的xpath.

Dan*_*lau 13

获取XPath没有通用的方法,主要是因为没有一个通用的XPath可以识别文档中的特定节点.在某些模式中,节点将由属性唯一标识(id并且name可能是最常见的属性.)在其他模式中,每个元素的名称(即标记)足以唯一地标识节点.在一些(不太可能,但可能)的情况下,没有一个唯一的名称或属性将您带到特定节点,因此您需要使用基数(获得第一个孩子的第n个孩子). ..).

编辑:在大多数情况下,创建一个与模式相关的函数来组装给定节点的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") + "']";
}
Run Code Online (Sandbox Code Playgroud)


Luk*_*der 13

我在jOOX背后的公司工作,这是一个为Java标准DOM API提供许多有用扩展的库,模仿jquery API.使用jOOX,您可以获得任何元素的XPath,如下所示:

String path = $(element).xpath();
Run Code Online (Sandbox Code Playgroud)

上面的路径就是这样的

/document[1]/library[2]/books[3]/book[1]
Run Code Online (Sandbox Code Playgroud)


TAN*_*N70 7

我从Mikkel Flindt发布了这段代码并 对其进行了修改,以便它可以用于属性节点.

public static String getFullXPath(Node n) {
// abort early
if (null == n)
  return null;

// declarations
Node parent = null;
Stack<Node> hierarchy = new Stack<Node>();
StringBuffer buffer = new StringBuffer();

// push element on stack
hierarchy.push(n);

switch (n.getNodeType()) {
case Node.ATTRIBUTE_NODE:
  parent = ((Attr) n).getOwnerElement();
  break;
case Node.ELEMENT_NODE:
  parent = n.getParentNode();
  break;
case Node.DOCUMENT_NODE:
  parent = n.getParentNode();
  break;
default:
  throw new IllegalStateException("Unexpected Node type" + n.getNodeType());
}

while (null != parent && parent.getNodeType() != Node.DOCUMENT_NODE) {
  // push on stack
  hierarchy.push(parent);

  // get parent of parent
  parent = parent.getParentNode();
}

// construct xpath
Object obj = null;
while (!hierarchy.isEmpty() && null != (obj = hierarchy.pop())) {
  Node node = (Node) obj;
  boolean handled = false;

  if (node.getNodeType() == Node.ELEMENT_NODE) {
    Element e = (Element) node;

    // is this the root element?
    if (buffer.length() == 0) {
      // root element - simply append element name
      buffer.append(node.getNodeName());
    } else {
      // child element - append slash and element name
      buffer.append("/");
      buffer.append(node.getNodeName());

      if (node.hasAttributes()) {
        // see if the element has a name or id attribute
        if (e.hasAttribute("id")) {
          // id attribute found - use that
          buffer.append("[@id='" + e.getAttribute("id") + "']");
          handled = true;
        } else if (e.hasAttribute("name")) {
          // name attribute found - use that
          buffer.append("[@name='" + e.getAttribute("name") + "']");
          handled = true;
        }
      }

      if (!handled) {
        // no known attribute we could use - get sibling index
        int prev_siblings = 1;
        Node prev_sibling = node.getPreviousSibling();
        while (null != prev_sibling) {
          if (prev_sibling.getNodeType() == node.getNodeType()) {
            if (prev_sibling.getNodeName().equalsIgnoreCase(
                node.getNodeName())) {
              prev_siblings++;
            }
          }
          prev_sibling = prev_sibling.getPreviousSibling();
        }
        buffer.append("[" + prev_siblings + "]");
      }
    }
  } else if (node.getNodeType() == Node.ATTRIBUTE_NODE) {
    buffer.append("/@");
    buffer.append(node.getNodeName());
  }
}
// return buffer
return buffer.toString();
}          
Run Code Online (Sandbox Code Playgroud)


Ale*_*lex 7

对我来说这个最好用(使用org.w3c.dom元素):

String getXPath(Node node)
{
    Node parent = node.getParentNode();
    if (parent == null)
    {
        return "";
    }
    return getXPath(parent) + "/" + node.getNodeName();
}
Run Code Online (Sandbox Code Playgroud)

  • 计数器(即“html[1]/div[3]”)怎么样? (3认同)