Digester解析xml文件

     一般用来读取xml文件的工具包有DOM、SAX和JDOM等,但用过的人都知道,它们属于比较底层的API,写起来代码量很大,而且如果修改了xml文件的格式,代码也要做大幅度的改动。而使用Apache Ja...

    

一般用来读取xml文件的工具包有DOMSAXJDOM等,但用过的人都知道,它们属于比较底层的API,写起来代码量很大,而且如果修改了xml文件的格式,代码也要做大幅度的改动。而使用Apache JakartaDigester,解析XML文件非常方便且不需要过多的关心底层的具体解析过程。Digester本来仅仅是Jakarta Struts中的一个工具,用于处理struts-config.xml配置文件。显然,将XML文件转换成相应的Java对象是一项很通用的功能,这个工具理应具有更广泛的用途,所以很快它就在Jakarta Commons项目(用于提供可重用的Java组件库)中有了一席之地。Digester"事件"驱动,通过调用预定义的规则操作对象栈,将XML文件转换为Java对象。

工作原理如下: Digester底层采用SAX(Simple API for XML)XML文件,所以很自然的,对象转换由"事件"驱动,在遍历每个节点时,检查是否有匹配模式,如果有,则执行规则定义的操作,比如创建特定的Java对象,或调用特定对象的方法等。此处的XML元素根据匹配模式(matching pattern)识别,而相关操作由规则(rule)定义。

如下xml代码,右边是左边元素对应的匹配模式:

attachments-2017-11-vTq1zzQn5a0ea2d24ddb1.png

下面是存放地址及编码的xml文件viewcache.xml(片段)

下面介绍解析xml文件的代码

例子1

attachments-2017-11-EMoRWkRM5a0ea308a1f47.png

xml文件分3层结构,分别为:

<viewcache>节点其下包含1<areas>节点

<areas>节点其下包含多个<area>节点

<area>节点,其下包含各种信息节点如:<id> <name>等。 

我们的操作目标是把area中的信息节点的内容提取出来。 
把每个<arrea>看做为一个对象,<area>中信息节点的内容为对象中的元素。 
设定一个类Area.java 其内容如下:

attachments-2017-11-g54aac9g5a0ea33de6b73.png

创建一个ViewCache类,用来保存解析后的所有对象:

attachments-2017-11-9Svdikmq5a0ea3731b1af.png
创建一个类AreaDigester,对xml文件进行解析:

    attachments-2017-11-AxZ1bZPY5a0ea3accbf93.png

    

调用AreaDigesterdigester方法,即可把解析后的所有地址对象,存放在ViewCachelist中。

 

 

例子2

要解析的xml文件books.xml如下:

attachments-2017-11-s8Be1Gy25a0ea3f9aa217.png

    Library类如下:

attachments-2017-11-PbnPexUd5a0ea438e21c7.png

    

Book类如下:

attachments-2017-11-miOnwDvE5a0ea467a6dd8.png

Chapter类如下:


attachments-2017-11-q3c7hVaq5a0ea49024790.png



        

解析xml的类如下:

1.      public class MainTest {  

2.        

3.          /** 

4.           * @param args 

5.           */  

6.          public static void main(String[] args) {  

7.              // 建立一个Digester对象  

8.              Digester digester = new Digester();  

9.              //指定它不要用DTD验证XML文档的合法性——这是因为我们没有为XML文档定义DTD  

10.          digester.setValidating(false);  

11.          // library标签开始解析,并新建一个Library对象做为根对象  

12.          digester.addObjectCreate("library", Library.class);  

13.          // 根据library标签属性值设置对象的属性,一次可以设置多个属性  

14.          digester.addSetProperties("library");  

15.          // 也可以用下面的方法,指定propertyName  

16.          // digester.addSetProperties("library", "name", "name");  

17.    

18.          // -----1层元素开始  

19.          digester.addObjectCreate("library/book", Book.class);  

20.          //digester.addSetProperties("library/book");  

21.          // 可以用以下三条语句代替  

22.          digester.addCallMethod("library/book", "setBookInfo", 2);  

23.          digester.addCallParam("library/book", 0, "title");  

24.          digester.addCallParam("library/book", 1, "author");  

25.          /** 

26.           * addCallParam(String rule, int  paraIndex,String attributeName) 

27.           * 该方法与addCallMethod配合使用 

28.           * int paraIndex:表明需要填充的方法形参序号, 0 开始,方法由addCallMethod指定 

29.           * String attributeName:指定标签属性名称 

30.           */  

31.            

32.            

33.          // -----2层元素开始  

34.          digester.addObjectCreate("library/book/chapter", Chapter.class);  

35.          /** addBeanPropertySetter()是将子节点转换为对象的属性,这个方法还可以有第二个参数,当对象的属性名和子节点的名字不一样时用来指定对象的属性名 

36.              该方法的作用及使用方法类似于addSetProperties,只不过它是用String rule规则所指定标签的值(而不是标签的属性)来调用对象的setter*/  

37.          digester.addBeanPropertySetter("library/book/chapter/no");  

38.          // digester.addBeanPropertySetter("library/book/chapter/no", "no");  

39.            

40.          /** addCallMethod(String rule,String methodName, int  paraNumber) 方法 

41.           * 同样是设置对象的属性,但是方式更加灵活,不需要对象具有setter 

42.           * paraNumber = 0,可以单独使用(表明为标签的值来调用),不然需要配合addCallParam方法 

43.          */  

44.          // digester.addBeanPropertySetter("library/book/chapter/caption");  

45.          // 下面的方法,可以用来代替上一句,作用是一样的   

46.          digester.addCallMethod("library/book/chapter/caption", "setCaption", 0);  

47.    

48.          // addSetNext()是说在再次遇到匹配节点后, 调用当前对象(Chapter类的对象)的父对象(Book类的对象)的方法,方法参数是当前层元素的对象  

49.          digester.addSetNext("library/book/chapter", "addChapter");  

50.          // -----2层元素结束  

51.    

52.          digester.addSetNext("library/book", "addBook");  

53.          // -----1层元素结束  

54.    

55.          try {  

56.              // 解析XML文件,并得到ROOT元素  

57.              Library library = (Library) digester.parse(MainTest.class.getResourceAsStream("books.xml"));  

58.              System.out.println(" 图书馆: " + library.getName());  

59.              System.out.println(" 共藏书: " + library.getBookList().size() + "  ");  

60.              System.out.println(" ***************************** ");  

61.    

62.              for (Book book : library.getBookList()) {  

63.                  System.out.println(" 书名: " + book.getTitle() + "        作者: " + book.getAuthor());  

64.                  System.out.println(" ------------------------------ ");  

65.                  // 显示章节  

66.                  System.out.println("  " + book.getChapters().size() + "  ");  

67.                  for (Chapter chapter : book.getChapters()) {  

68.                      System.out.println(chapter.getNo() + ": " + chapter.getCaption());  

69.                  }  

70.                  System.out.println(" ------------------------------ ");  

71.              }  

72.          } catch (IOException e) {  

73.              e.printStackTrace();  

74.          } catch (SAXException e) {  

75.              e.printStackTrace();  

76.          }  

77.      }  

78.  }  

 

Digester解析xml的规则,除了在java类中描述设置之外,还可以把解析规则放在xml文件中。以例子2中的代码为例,规则在books-rule.xml文件中,内容如下:(The DTD is distributed in the commons-digester.jar. It can be found at org/apache/commons/digester/xmlrules/digester-rules.dtd,通过查看DTD文件,可以知道有哪些标签可以使用)

 

1.      <?xml version="1.0" encoding="UTF-8" ?>  

2.      <!DOCTYPE digester-rules PUBLIC  

3.         "-//Jakarta Apache //DTD digester-rules XML V1.0//EN"  

4.         "digester-rules.dtd">   

5.      <digester-rules>    

6.          <object-create-rule pattern="library" classname="com.alibaba.chj.digester.Library" />    

7.          <set-properties-rule pattern="library">    

8.              <alias attr-name="name" prop-name="name" />    

9.          </set-properties-rule>    

10.      <pattern value="library/book">    

11.          <object-create-rule classname="com.alibaba.chj.digester.Book" />    

12.          <set-properties-rule />    

13.          <pattern value="chapter">    

14.              <object-create-rule classname="com.alibaba.chj.digester.Chapter" />    

15.              <bean-property-setter-rule pattern="no" propertyname="no" />  

16.              <bean-property-setter-rule pattern="caption" propertyname="caption" />  

17.              <set-next-rule methodname="addChapter" />    

18.          </pattern>       

19.          <set-next-rule methodname="addBook" />    

20.      </pattern>    

21.  </digester-rules>    

 

解析xml类的代码,修改为:

1.      public class MainTest {  

2.        

3.          /** 

4.           * @param args 

5.           */  

6.          public static void main(String[] args) {  

7.              try {      

8.                  Digester digester = DigesterLoader.createDigester(DigesterXmlRuleTest.class.getResource("books-rule.xml"));      

9.                  Library library = (Library) digester.parse(DigesterXmlRuleTest.class.getResourceAsStream("books.xml"));      

10.              System.out.println(" 图书馆: " + library.getName());  

11.              System.out.println(" 共藏书: " + library.getBookList().size() + "  ");  

12.              System.out.println(" ***************************** ");  

13.    

14.              for (Book book : library.getBookList()) {  

15.                  System.out.println(" 书名: " + book.getTitle() + "        作者: " + book.getAuthor());  

16.                  System.out.println(" ------------------------------ ");  

17.                  // 显示章节  

18.                  System.out.println("  " + book.getChapters().size() + "  ");  

19.                  for (Chapter chapter : book.getChapters()) {  

20.                      System.out.println(chapter.getNo() + ": " + chapter.getCaption());  

21.                  }  

22.                  System.out.println(" ------------------------------ ");  

23.              }     

24.          } catch (IOException e) {  

25.              e.printStackTrace();  

26.          } catch (SAXException e) {  

27.              e.printStackTrace();  

28.          }   

29.      }  

30.  }  





















  • 发表于 2017-11-17 16:59
  • 阅读 ( 1282 )
  • 分类:Java

你可能感兴趣的文章

相关问题

0 条评论

请先 登录 后评论
不写代码的码农
HJ社区-肖峰

IT

29 篇文章

作家榜 »

  1. 威猛的小站长 124 文章
  2. Jonny 65 文章
  3. 江南烟雨 36 文章
  4. - Nightmare 33 文章
  5. doublechina 31 文章
  6. HJ社区-肖峰 29 文章
  7. 伪摄影 22 文章
  8. Alan 14 文章