获取DOM树中所有根到叶路径的列表

时间:2016-01-12 19:53:47

标签: java xml dom tree

到目前为止,我理解当我将XML解析为DOM对象时,它表示为树。我试图通过TreeWalker获取从root到我的XML文档(n-ary树)的任何叶子的所有路径的列表,但是我想知道我是否应该自己执行或者&#&# 39;定义了任何现有的实现。我在官方文档中找不到任何内容。

给出xml文档:

<node id="A">
   <node id = "AA">
       <node id = "AAA"></node>
   </node>
   <node id = "AB">
   </node>
   <node id = "AC">
   </node>
</node>

预期列表应包含:

A, AA, AAA 
A, AB
A, AC

2 个答案:

答案 0 :(得分:1)

我会使用这样的算法:

使用一个函数在树中向下,如果没有子节点,则向上输出每个父节点。

 function deep(node n){
    if(n has childs)
       foreach(child c) {
          deep(c);
       }
    else goup(n);
 }

 function goup(node n){
     if(node has no parent) echo n.id
     else echo goup(n.parent()) . ", " . n.id
 }

答案 1 :(得分:0)

非递归TreeWalker

这很简单。找到所有叶元素,然后通过遍历父链来显示路径。

NodeFilter leafElements = new NodeFilter() {
    @Override
    public short acceptNode(Node node) {
        for (Node child = node.getFirstChild(); child != null; child = child.getNextSibling())
            if (child.getNodeType() == Node.ELEMENT_NODE)
                return NodeFilter.FILTER_SKIP;
        return NodeFilter.FILTER_ACCEPT;
    }
};
TreeWalker walker = ((DocumentTraversal)document).createTreeWalker(document.getDocumentElement(),
                                                                   NodeFilter.SHOW_ELEMENT,
                                                                   leafElements,
                                                                   false);
for (Element leaf; (leaf = (Element)walker.nextNode()) != null; ) {
    Deque<String> path = new ArrayDeque<>();
    for (Node node = leaf; node.getNodeType() == Node.ELEMENT_NODE; node = node.getParentNode())
        path.addFirst(((Element)node).getAttribute("id"));
    System.out.println(path);
}

<强>输出

[A, AA, AAA]
[A, AB]
[A, AC]

简单递归

也相当简单。递归后代,保持目前为止的路径,并打印叶元素。

showLeafPaths(document.getDocumentElement(), new StringBuilder());
private static void showLeafPaths(Element elem, StringBuilder path) {
    final int pathLen = path.length();
    if (pathLen != 0)
        path.append(", ");
    path.append(elem.getAttribute("id"));
    boolean hasChild = false;
    for (Node child = elem.getFirstChild(); child != null; child = child.getNextSibling())
        if (child.getNodeType() == Node.ELEMENT_NODE) {
            hasChild = true;
            showLeafPaths((Element)child, path);
        }
    if (! hasChild)
        System.out.println(path);
    path.setLength(pathLen);
}

<强>输出

A, AA, AAA
A, AB
A, AC