前两天,公司想要开发自己的一套简易的报表处理系统,其中要用XML来存储报表的配置信息,其中就牵扯到了XML的解析工作。我刚好也就负责的是解析XML这个模块,在实现这段功能的时候用到了JDOM+XPATH。顺便写出来,便于以后借鉴。


 

    一、什么是JDOM?

    JDOM是两位著名的 Java 开发人员兼作者,Brett Mclaughlin 和 Jason Hunter 的创作成果。其作用是用于快速开发XML相关应用程序。

具体参见:http://baike.baidu.com/view/1569983.htm

    二、什么是XPath?

    XPath是一门用于在XML查找信息的语言,可以通过元素和属性进行导航。

    XPath是W3C标准的主要元素,并且XQuery和Xpointer都是构建于XPath之上的,因此,对XPath的理解是很多高级XML应用的基础。

具体参见:http://www.w3school.com.cn/xpath/

    三、需要的jar包

    jdom-1.0.jar:顾名思义,jdom的jar包

下载链接:http://down.51cto.com/data/487203

    jaxen-1.1.1.jar:虽然jdom包中已经有了org.jdom.xpath,提供了对于Xpath的支持,但是并不完全,需要该jar包给予进一步Xpath支持。如果不加入该包,使用Xpath将会报出:java.lang.NoClassDefFoundError: org/jaxen/BaseXPath的错误。

下载链接:http://down.51cto.com/data/150977

    四、具体开发

    JDOM中提供SAXBuilder对象来解析XML,提供Document来代表整个XML文档,提供Element来代表具体节点,提供Attribute来代表具体属性。可以很好的告别工厂之类繁杂的操作,下面是利用JDOM来解析1个XML,获得XML根节点的实例:

 

  1. public Element readFile(String pathStr) {  
  2.         Document doc = null;  
  3.           
  4.         //创建解析对象  
  5.         SAXBuilder builder = new SAXBuilder();  
  6.           
  7.         try {  
  8.             doc = builder.build(pathStr);  
  9.         } catch (JDOMException e) {  
  10.             e.printStackTrace();  
  11.         } catch (IOException e) {  
  12.             e.printStackTrace();  
  13.         }  
  14.           
  15.         //获取根节点  
  16.         Element root = doc.getRootElement();  
  17.         return root;  
  18.     } 

    XPath允许我们直接通过节点或者属性访问指定的节点,例如XML文件是这样的:

 

  1. TemplateFolder<ReportConfig> 
  2.   <Respority> 
  3.       <TemplateFolder>D:/tfqy</TemplateFolder>   
  4.   </Respority> 
  5.   <Reports> 
  6.       <Report name="report1" ConfigFile="Cfg-Report1.xml"/> 
  7.         <Report name="report2" ConfigFile="Cfg-Report2.xml"/> 
  8.   </Reports> 
  9. </ReportConfig> 

那么,我们可以通过以下代码直接获得到TemplateFolder节点的值:

     

    1. List<Element> Respority = null;  
    2.         try {  
    3.             Respority = XPath.selectNodes(root, "/ReportConfig/Respority/TemplateFolder");  
    4.         } catch (JDOMException e) {  
    5.             e.printStackTrace();  
    6.         }  
    7.         for (Element element : Respority) {  
    8.             excelPath = element.getText();  
    9.         } 


    在这里需要注意,通过selectNodes获得的会是Respority节点下TemplateFolder这个节点的List集合,即使你明确知道TemplateFolder节点只会有一个,也必须用List来接收

    五、XPath的语法规则

        通过上面的例子已经可以简单的获取一些节点对象了,既然XPath是通过元素以及属性来导航到指定节点的,那么XPath的语法规则是怎么样的呢?

    总的来说XPath的语法规则表现称之为路径表达式

    下面列出了常用的几个路径表达式:

    表达式 描述
    nodename 选取此节点的所有子节点。
    / 从根节点选取。
    // 从匹配选择的当前节点选择文档中的节点,而不考虑它们的位置。
    . 选取当前节点。
    .. 选取当前节点的父节点。
    @ 选取属性。

     

    在有了路径表达式的基础上使用谓语,可以更加精确的定位到具体元素(PS:实例代码中并没有使用谓语,是想突出显示强转会带来一个错误的事实。)

    路径表达式 结果
    /bookstore/book[1] 选取属于 bookstore 子元素的第一个 book 元素。
    /bookstore/book[last()] 选取属于 bookstore 子元素的最后一个 book 元素。
    /bookstore/book[last()-1] 选取属于 bookstore 子元素的倒数第二个 book 元素。
    /bookstore/book[position()<3] 选取最前面的两个属于 bookstore 元素的子元素的 book 元素。
    //title[@lang] 选取所有拥有名为 lang 的属性的 title 元素。
    //title[@lang='eng'] 选取所有 title 元素,且这些元素拥有值为 eng 的 lang 属性。
    /bookstore/book[price>35.00] 选取 bookstore 元素的所有 book 元素,且其中的 price 元素的值须大于 35.00。
    /bookstore/book[price>35.00]/title 选取 bookstore 元素中的 book 元素的所有 title 元素,且其中的 price 元素的值须大于 35.00。

     在有了谓语的基础上当我们需要查找一切不确定的节点时还可以使用通配符来实现

    下面列出了XPath常用的通配符

    通配符 描述
    * 匹配任何元素节点。
    @* 匹配任何属性节点。
    node() 匹配任何类型的节点。

          最后还有一个运算符“|”其作用就是可以选取多个路径

          另外还有一些相对复杂的轴,节点测试,运算符之类的就不一一列举了,其具体的使用规则参照W3School中关于XPath的部分就可以了。

          最后,祝大家XML解析快乐~