/**
 * <b>function:</b>用xpath遍历xml信息
 * @author hoojo
 * @createDate 2011-8-4 下午04:56:52
* xpath参考:http://www.w3school.com.cn/xpath/xpath_functions.asp
 * 
 *     nodeName 选取此节点的所有子节点 
    /    从根节点选取 
    //   从匹配选择的当前节点选择文档中的节点,而不考虑它们的 
    .    选取当前节点 
    ..   选取当前节点的父节点 
    @  选取属性 
    
    * 匹配任何元素节点 
    @* 匹配任何属性节点 
    node() 配任何类型的节点 
    
    ancestor 选取当前节点的所有先辈(父、祖父等) 
    ancestor-or-self 选取当前节点的所有先辈(父、祖父等)以及当前节点本身 
    attribute 选取当前节点的所有属性 
    child 选取当前节点的所有子元素。 
    descendant 选取当前节点的所有后代元素(子、孙等)。 
    descendant-or-self 选取当前节点的所有后代元素(子、孙等)以及当前节点本身。 
    following 选取文档中当前节点的结束标签之后的所有节点。 
    namespace 选取当前节点的所有命名空间节点 
    parent 选取当前节点的父节点。 
    preceding 选取文档中当前节点的开始标签之前的所有节点。 
    preceding-sibling 选取当前节点之前的所有同级节点。 
    self 选取当前节点。
    
    child::book 选取所有属于当前节点的子元素的 book 节点 
    attribute::languane 选取当前节点的 languange 属性 
    child::* 选取当前节点的所有子元素 
    attribute::* 选取当前节点的所有属性 
    child::text() 选取当前节点的所有文本子节点 
    child::node() 选取当前节点的所有子节点 
    descendant::book 选取当前节点的所有 book 后代 
    ancestor::book 选择当前节点的所有 book 先辈
 */
@SuppressWarnings("unchecked")@Test
public void queryElementByXPath() {    SAXBuilder builder = new SAXBuilder();
    try {        Document doc = builder.build(new File("file/disk.xml"));        List<Element> list = XPath.selectNodes(doc, "/HD/disk");
        for (Element el : list) {            String name = el.getAttributeValue("name");            String capacity = el.getChildText("capacity");            String directories = el.getChildText("directories");            String files = el.getChildText("files");            System.out.println("磁盘信息:");            System.out.println("分区盘符:" + name);            System.out.println("分区容量:" + capacity);            System.out.println("目录数:" + directories);            System.out.print("文件数:" + files);            
            String capacityText = ((Text) XPath.selectSingleNode(el, "//disk[@name='" + name + "']/capacity/text()")).getTextNormalize();
            System.out.println("#" + capacityText);            
            System.out.println("-----------------------------------");        }
        //显示文档信息
        System.out.println("#############显示文档信息###############");        print(0, doc.getContent());
        
        //获得hd元素
        System.out.println("#############显示HD子元素信息###############");        Element root = (Element) XPath.selectSingleNode(doc, "/HD");
        //fail(root.getChildren().size());
        print(0, root.getChildren());
        
        //获取hd下所有元素
        System.out.println("#############显示HD子元素信息###############");        List roots = (List) XPath.selectNodes(doc, "/HD/*");
        //fail(roots.size());
        print(0, roots);
        
        //获得hd下的所有disk元素
        System.out.println("#############显示disk信息###############");        roots = (List) XPath.selectNodes(doc, "/HD/disk");
        //fail(roots.size());
        print(0, roots);
        
        System.out.println("#############显示disk2信息###############");        roots = (List) XPath.selectNodes(doc, "/HD/disk2");
        print(0, roots);
        
        System.out.println("#############显示任意路径下的files信息###############");        roots = (List) XPath.selectNodes(doc, "//files");
        print(0, roots);
        
        System.out.println("#############显示任意路径下的files指定下标的file信息###############");        roots = (List) XPath.selectNodes(doc, "//files/file[1]");
        print(0, roots);
        
        System.out.println("#############显示任意路径下的files最后的file信息###############");        roots = (List) XPath.selectNodes(doc, "//files/file[last()]");
        print(0, roots);
        
        System.out.println("#############显示任意路径下的files倒数第二的file信息###############");        roots = (List) XPath.selectNodes(doc, "//files/file[last() - 1]");
        print(0, roots);
 
        System.out.println("#############显示任意路径下的files的子元素file位置position在第二的file信息###############");        roots = (List) XPath.selectNodes(doc, "//files/file[position() = 2]");
        //roots = (List) XPath.selectNodes(doc, "//files/file[position() > 2]");
        print(0, roots);
        
        System.out.println("#############显示任意路径下的files第三个file的当前节点的前面所有同级节点信息###############");        roots = (List) XPath.selectNodes(doc, "//files/file[3]/preceding-sibling::*");
        print(0, roots);
        
        System.out.println("#############显示任意路径下的disk2之前的所有节点信息###############");        roots = (List) XPath.selectNodes(doc, "//disk2/preceding::*");
        print(0, roots);
        
        System.out.println("#############显示任意路径下的disk2之后的所有节点信息###############");        roots = (List) XPath.selectNodes(doc, "//disk2/following::*");
        print(0, roots);
        
        System.out.println("#############显示任意路径下的files的所有属性信息###############");        roots = (List) XPath.selectNodes(doc, "//files/attribute::*");
        fail(getAttrInfo(roots));
        
        System.out.println("#############显示任意路径下的节点是disk属性name=C的信息###############");        roots = (List) XPath.selectNodes(doc, "//disk[@name='C']");
        print(0, roots);
        
        System.out.println("#############显示任意路径下的节点是disk的子元素的文本中含义5和8节点的信息###############");        roots = (List) XPath.selectNodes(doc, "//disk/child::*[contains(text(), '8') and contains(text(), '5')]");
        //roots = (List) XPath.selectNodes(doc, "//disk/child::*[contains(text(), '8') or contains(text(), '5')]");
        print(0, roots);
 
        System.out.println("#############显示任意路径下的节点是files且有属性size的信息###############");        roots = (List) XPath.selectNodes(doc, "//files[@size]");
        print(0, roots);
 
        System.out.println("#############显示HD节点下capacity的值为11G的信息###############");        //roots = (List) XPath.selectNodes(doc, "/HD/disk/capacity[text()='11G']");
        roots = (List) XPath.selectNodes(doc, "/HD/*/capacity[text()='11G']");
        //roots = (List) XPath.selectNodes(doc, "/*/*/capacity[text()='11G']");
        print(0, roots);
        
        //parent::*表示父节点集合
        System.out.println("#############显示任意路径下的节点是files且属性size有值的父节点的信息###############");        roots = (List) XPath.selectNodes(doc, "//files[@size='200']/parent::*");
        print(0, roots);
        
        System.out.println("#############显示任意路径下的节点disk的子节点的capacity信息###############");        roots = (List) XPath.selectNodes(doc, "//disk/child::capacity");
        print(0, roots);
        
        //获取c盘的大小
        System.out.println("获取c盘的大小");        Text filesText = (Text) XPath.selectSingleNode(doc, "/HD/disk[@name='C']/files/text()");
        System.out.println(filesText.getTextNormalize());
        
        //XPath function
        /**
        string concat (string, string, string*)  联接两个字符串 
        boolean starts-with (string, string)  判断某字符串是否以另一字符串开头 
        boolean contains (string, string)  判断某字符串是否包含另一字符串 
        string substring (string, number, number)  取子字符串 
        number string-length (string)  测字符串长度 
        number sum (node-set)  求和 
        number floor (number)  求小于此数的最大整数值 
        number ceiling (number)  求大于此数最小整数值
        **/ 
 
        System.out.println("获取@size的和大于200的");        roots = (List) XPath.selectNodes(doc, "//files[sum(@size) > 200]");
        print(0, roots);
 
        System.out.println("查找directories的内容长度小于3的");        roots = (List) XPath.selectNodes(doc, "//directories[string-length(text()) < 3]");
        print(0, roots);
        
        System.out.println("查找files的内容包含5的");        roots = (List) XPath.selectNodes(doc, "//files[contains(text(), '5')]");
        print(0, roots);
    } catch (JDOMException e) {        e.printStackTrace();
    } catch (IOException e) {        e.printStackTrace();
    } 
}