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

如何使用java为XML中的节点生成Xpath?,java,xml,xpath,Java,Xml,Xpath,我有一段代码为节点生成xpath。但它并没有创建它的数组结构。例如,如果一个元素有两个同名的元素,我需要提供相应的索引来指向它们。下面是一个例子 <abc> <def> </hij> </def> <def> </lmn> </def> </abc> 要获取lmn的xpath,我需要如下内容: //abc[1]/def[1]/hij //abc[1]/def[2

我有一段代码为节点生成xpath。但它并没有创建它的数组结构。例如,如果一个元素有两个同名的元素,我需要提供相应的索引来指向它们。下面是一个例子

<abc>
  <def>
     </hij>
  </def>
  <def>
     </lmn>
  </def>
</abc>
要获取
lmn
的xpath,我需要如下内容:

//abc[1]/def[1]/hij
//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;
    }
私有字符串getXPath(节点根,字符串elementName) { 对于(int i=0;i0) { if(map.containsKey(node.getNodeName())) map.put(node.getNodeName(),map.get(node.getNodeName())+1); 其他的 put(node.getNodeName(),1); this.xpath=getXPath(节点,elementName); if(this.xpath!=null){ 返回“\\”+node.getNodeName()+”[“+map.get(node.getNodeName())+“]”+this.xpath; } } } } 返回null; } 有人能帮我用这个附加数组结构吗?


<abc>
  <def>
    </hij>
  </def>
  <def>
    </lmn>
  </def>
</abc>
在这里。你快关门了

</hij> 


没有打开它们。如果您在abc之前打开它们,则不能在abc内部关闭它们。 基本上:你不能缠绕它们。 开一,开二,关二,关一。永远不要用另一种方式


这可能会导致您的错误

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

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

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

</lmn>
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]