查找相同级别或更高级别的XML节点数

时间:2015-02-28 20:36:40

标签: java xml xpath

我想找到与@ title =“d”或更高级别的节点处于同一级别的节点数

XML:

<item title="a">
       <item title="b">               
           <item title="c"></item>
           <item title="d">  
               <item title="e"></item>  
               <item title="f"></item>
           </item>                 
       </item> 
       <item title="x">             
           <item title="y"></item> 
           <item title="z"></item>  
       </item>            
</item> 
L0 . . . . . .  a . . . .
              /   \
L1 . . . . . b . . x .  .
           /  \   / \
L2 . . . .c . d .y . z  .
             / \
L3 . . . . .e . f . . . .

一些例子:

System.out.println(leftDomainSize("d")); // 7
System.out.println(leftDomainSize("x")); // 3
System.out.println(leftDomainSize("e")); // 9

代码:

public int leftDomainSize(String s){
        DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
        DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
        Document document = documentBuilder.parse(path);
        //????
}

3 个答案:

答案 0 :(得分:1)

Pure XPath解决方案:

您可以计算其祖先计数小于或等于给定项目的祖先计数的项目数。因此,对于标题等于'd'的项目:

count(//item[count(//item[@title='d']/ancestor::item) >= count(ancestor::item)])

7

也适用于您的其他示例:

count(//item[count(//item[@title='x']/ancestor::item) >= count(ancestor::item)])

3

count(//item[count(//item[@title='e']/ancestor::item) >= count(ancestor::item)])

9

答案 1 :(得分:0)

您可以使用广度优先搜索,如下所示:

public int leftDomainSize(String s) throws Exception{
    class Pair {
        Element elem;
        int depth;

        public Pair(Element elem, int depth) {
            this.elem = elem;
            this.depth = depth;
        }
    }

    DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
    DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();

    Document document = documentBuilder.parse(path);
    Element root = document.getDocumentElement();

    // Breadth First Search
    LinkedList<Pair> queue = new LinkedList<Pair>();
    int depth = Integer.MAX_VALUE;
    queue.add(new Pair(root, 1));
    int result = 0;
    while(!queue.isEmpty()) {
        Pair curr = queue.remove();
        if(curr.depth > depth) {
            continue;
        }
        result++;
        if (curr.elem.getAttribute("title").equals(s)) {
            depth = curr.depth;
        }
        NodeList children = curr.elem.getChildNodes();
        for(int i = 0; i<children.getLength(); i++) {
            Node child = children.item(i);
            if(child instanceof Element) {
                queue.add(new Pair((Element)child, curr.depth + 1));
            }
        }
    }
    return result;
}

答案 2 :(得分:0)

尝试此功能,它应该通过反向查看父节点及其子节点

来工作
public int findNodes(Node node)
{
  int count = 0;
  Node parent = null;
  do
  {
    parent = node.getParentNode();
    if(parent==null)break;
    NodeList list = parent.getChildNodes();
    count += list.getLength();
    node = parent;
  }
  while(parent != null);
  return count;
}