【问题标题】:Get XPath of Substring in an XML Document获取 XML 文档中子字符串的 XPath
【发布时间】:2013-01-22 08:58:21
【问题描述】:

我需要在 XML 文档中找到文本元素的确切 XPath。我认为这样做的一种方法是将 Document 转换为字符串,在子字符串周围添加一个临时标记,将其转换回 Document,然后找到 XPath。

这是我目前所拥有的:

public String findXPathInXMLString(int startIndex, int endIndex, String string) throws IOException, ParserConfigurationException, SAXException {
    Conversion conversion = new Conversion();
    String xpath;

    //Step 1. Replace start to end index with temporary tag in string document
    StringBuilder stringBuilder = new StringBuilder(string);
    stringBuilder.replace(startIndex, endIndex, "<findXPathInXMLStringTemporaryTag>" + string.substring(startIndex, endIndex) + "</findXPathInXMLStringTemporaryTag>");

    //Step 2. Convert string document to DOM document & Find XPath of temporary tag in DOM document
    xpath = "/" + getXPath(conversion.stringToDocument(stringBuilder.toString()), "findXPathInXMLStringTemporaryTag");

    //Step 3. Cut off last part of the XPath
    //xpath = xpath.substring(0, 2).replace("/documentXPathTemporaryTag", "");

    //Step 4. Return the XPath
    return xpath;
}

public String getXPath(Document root, String elementName) {
    try {
        XPathExpression expr = XPathFactory.newInstance().newXPath().compile("//" + elementName);
        Node node = (Node) expr.evaluate(root, XPathConstants.NODE);

        if (node != null) {
            return getXPath(node);
        }
    } catch (XPathExpressionException e) {
    }

    return null;
}

public String getXPath(Node node) {
    if (node == null || node.getNodeType() != Node.ELEMENT_NODE) {
        return "";
    }
    return getXPath(node.getParentNode()) + "/" + node.getNodeName();
}

到目前为止,我遇到的问题是方法 getXPath 没有放入 [x] 所以返回的 XPath 是错误的,因为子字符串可能在特定的 [3]rd 实例中标记在这种情况下,XPath 将应用于具有相同路径的所有节点。我想得到一个只能引用一个特定元素的确切路径。

【问题讨论】:

  • 这行不通。如果您在新节点中临时插入部分 XML,然后获取 XPath,则索引 ([x]) 可能会与其他情况不同。或许您应该向我们解释什么您的最终目标是什么以及为什么要这样做,有人可以告诉您如何去做。
  • 好吧,假设你有这个 XML &lt;root&gt;&lt;child&gt;&lt;gc /&gt;&lt;gc /&gt;&lt;/child&gt;&lt;/root&gt; 并且你想要第二个gc 的路径,所以你在它周围放置一个临时节点并得到&lt;root&gt;&lt;child&gt;&lt;gc /&gt;&lt;temp&gt;&lt;gc /&gt;&lt;/temp&gt;&lt;/child&gt;&lt;/root&gt;。现在你得到了temp 的路径,即/root/child/temp。您从该路径中删除/temp 以获取/root/child。这还没有获取到第二个gc的路径。
  • 您拒绝解释为什么要这样做有什么原因吗?
  • 你的意思是定义和未定义之间的完美平衡,对吧?
  • 在您明确定义并解释您要做什么之前,我无能为力。在您这样做之前,没有人可以提供帮助。

标签: java xml xpath


【解决方案1】:

好的,怎么样(ideone example):

我将 startIndexendIndex 更改为 index。临时节点可以附加到文本中的单个点。

public static String findXPathInXMLString(int index, String string) throws XPathExpressionException, SAXException, ParserConfigurationException, IOException {
    String xpath;

    //Step 1. Insert temporary tag in insert location
    StringBuilder stringBuilder = new StringBuilder(string);
    stringBuilder.insert(index, "<findXPathInXMLStringTemporaryTag />");

    Document document = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(
        new ByteArrayInputStream(stringBuilder.toString().getBytes())
      );

    //Step 2. Convert string document to DOM document & Find XPath of temporary tag in DOM document
    xpath = getXPath(document, "findXPathInXMLStringTemporaryTag");

    //Step 3. Cut off last part of the XPath
    xpath = xpath.replace("/findXPathInXMLStringTemporaryTag", "");

    //Step 4. Return the XPath
    return xpath;
}

private static String getXPath(Document root, String elementName) throws XPathExpressionException 
{
  XPathExpression expr = XPathFactory.newInstance().newXPath().compile("//"+elementName);
  Node node = (Node)expr.evaluate(root, XPathConstants.NODE);


  if(node != null) {
      return getXPath(node);
  }

  return null;
}

private static String getXPath(Node node) throws XPathExpressionException {
    if(node == null || node.getNodeType() != Node.ELEMENT_NODE) {
        return "";
    }

    return getXPath(node.getParentNode()) + "/" + node.getNodeName() + getIndex(node);
}

private static String getIndex(Node node) throws XPathExpressionException {
    XPathExpression expr = XPathFactory.newInstance().newXPath().compile("count(preceding-sibling::*[local-name() = '" + node.getNodeName() + "'])");
    int result = (int)(double)(Double)expr.evaluate(node, XPathConstants.NUMBER);

    if(result == 0){
        return "";
    }
    else {
        return "[" + (result + 1) + "]";
    }
}

【讨论】:

  • 非常好,非常好。非常感谢。到目前为止,它适用于我对其进行的所有测试。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-05-22
  • 1970-01-01
  • 1970-01-01
  • 2015-06-29
  • 2011-05-18
  • 1970-01-01
相关资源
最近更新 更多