java - 如何使用java为XML中的节点生成Xpath?

标签 java xml xpath

我有一段代码可以为节点生成 xpath。但它不会创建它的数组结构。例如,如果一个元素有两个同名的元素,我需要提供索引来适本地指向它们。下面是它的插图。

<abc>
  <def>
     </hij>
  </def>
  <def>
     </lmn>
  </def>
</abc>

现在,要获取 hij 的 xpath,我需要这样的东西:

//abc[1]/def[1]/hij

要获取 lmn 的 xpath,我需要这样的东西:

//abc[1]/def[2]/lmn

我有一段代码,它只会给我 //abc/def/hij//abc/def/lmn

private String getXPath(Node root, String elementName)
    {
        for (int i = 0; i < root.getChildNodes().getLength(); i++)
        {
            Node node = root.getChildNodes().item(i);
            if (node instanceof Element)
            {
                if (node.getNodeName().equals(elementName))
                {
                    return "\\" + node.getNodeName();
                }
                else if (node.getChildNodes().getLength() > 0)
                {
                    if(map.containsKey(node.getNodeName()))
                        map.put(node.getNodeName(), map.get(node.getNodeName())+1);
                    else
                        map.put(node.getNodeName(), 1);

                    this.xpath = getXPath(node, elementName);
                    if (this.xpath != null){
                        return "\\" + node.getNodeName() +"["+map.get(node.getNodeName())+"]"+ this.xpath;
                    }
                }
            }
        }

        return null;
    }

有人可以帮我用这个附加数组结构吗?

最佳答案

我无法修复问题中的代码,因为它不完整,例如 map 在哪里定义?另请参阅有关您的格式错误的输入的其他答案。

假设 hij 和 lmn 应该是短标签,这是一个完整的解决方案。

  • 我使用了使用 getParentNode() 向上导航树的方法。
  • 我已经包含了 XPath 测试来检查生成的表达式是否返回相同的节点
  • 扩展输入以包含同一级别的不同名称的元素。

代码

public class Test {

    private static String getXPath(Node root) {
        Node current = root;
        String output = "";
        while (current.getParentNode() != null) {
            Node parent = current.getParentNode();
            if (parent != null && parent.getChildNodes().getLength() > 1) {
                int nthChild = 1;
                Node siblingSearch = current;
                while ((siblingSearch = siblingSearch.getPreviousSibling()) != null) {
                    // only count siblings of same type
                    if (siblingSearch.getNodeName().equals(current.getNodeName())) {
                        nthChild++;
                    }
                }
                output = "/" + current.getNodeName() + "[" + nthChild + "]" + output;
            } else {
                output = "/" + current.getNodeName() + output;
            }
            current = current.getParentNode();
        }
        return output;
    }

    public static void main(String[] args) throws Exception {

        String input = "<abc><def><hij /></def><def><lmn /><xyz /><lmn /></def></abc>";
        Document root = DocumentBuilderFactory.newInstance()
                .newDocumentBuilder()
                .parse(new InputSource(new StringReader(input)));

        test(root.getDocumentElement(), root);
    }

    private static void test(Node node, Document doc) throws Exception {
        String expression = getXPath(node);
        Node result = (Node) XPathFactory.newInstance().newXPath()
                .compile(expression).evaluate(doc, XPathConstants.NODE);
        if (result == node) {
            System.out.println("Test OK  : " + expression);
        } else {
            System.out.println("Test Fail: " + expression);
        }
        for (int i = 0; i < node.getChildNodes().getLength(); i++) {
            test(node.getChildNodes().item(i), doc);
        }
    }
}

输出

Test OK  : /abc
Test OK  : /abc/def[1]
Test OK  : /abc/def[1]/hij
Test OK  : /abc/def[2]
Test OK  : /abc/def[2]/lmn[1]
Test OK  : /abc/def[2]/xyz[1]
Test OK  : /abc/def[2]/lmn[2]

关于java - 如何使用java为XML中的节点生成Xpath?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31072399/

相关文章:

java - 如何检查左尖括号键是否被按下?

java - Java中toString方法打印符号表

c# - 在可移植类库中包含 XPathSelectElement

c# - 无法使用 LINQ to XML 读取 XML 注释

java - 解析XML类型文件

xml - 如何获取当前节点变量的父节点元素?

python-3.x - lxml 不支持 xpath 上的多个属性过滤器

java - 从 Facebook SDK 中的 strings.xml 获取值

Java - 使用 CompletableFuture 链中断执行顺序

xpath - 在 selenium IDE 中组合 XPath 选择器