【问题标题】:How to generate Xpath for a node in XML using java?如何使用 java 为 XML 中的节点生成 Xpath?
【发布时间】:2015-06-26 11:46:20
【问题描述】:

我有一段代码可以为节点生成 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;
    }

有人可以帮我添加数组结构吗?

【问题讨论】:

    标签: java xml xpath


    【解决方案1】:

    我无法修复问题中的代码,因为它不完整,例如 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]
    

    【讨论】:

      【解决方案2】:
      <abc>
        <def>
          </hij>
        </def>
        <def>
          </lmn>
        </def>
      </abc>
      

      在这里。你正在关闭

      </hij> 
      

      </lmn>
      

      无需打开它们。如果您在 abc 之前打开它们,则无法在 abc 中关闭它们。 基本上:你不能将它们交织在一起。 打开一个,打开第二个,关闭第二个,关闭一个。永远不要换一种方式。

      这可能会导致您的错误

      【讨论】:

        猜你喜欢
        • 2011-06-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-11-30
        • 2015-08-22
        相关资源
        最近更新 更多