加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

Digester解析xml文件

发布时间:2020-12-16 05:51:01 所属栏目:百科 来源:网络整理
导读:刚刚学了一下Digester如何解析xml文件,所以记录下来,方便以后查看。 一般用来读取xml文件的工具包有DOM、SAX和JDOM等,但用过的人都知道,它们属于比较底层的API,写起来代码量很大,而且如果修改了xml文件的格式,代码也要做大幅度的改动。而使用Apache J

刚刚学了一下Digester如何解析xml文件,所以记录下来,方便以后查看。

一般用来读取xml文件的工具包有DOM、SAX和JDOM等,但用过的人都知道,它们属于比较底层的API,写起来代码量很大,而且如果修改了xml文件的格式,代码也要做大幅度的改动。而使用Apache Jakarta的Digester,解析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代码,右边是左边元素对应的匹配模式:

[xhtml] view plain copy
  1. <datasources>'datasources'
  2. <datasource>'datasources/datasource'
  3. <name/>'datasources/datasource/name'
  4. <driver/>'datasources/datasource/driver'
  5. </datasource>
  6. <datasource>'datasources/datasource'
  7. <name/>'datasources/datasource/name'
  8. <driver/>'datasources/datasource/driver'
  9. </datasource>
  10. </datasources>

例子1:

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

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

[xhtml] view plain copy
  1. <?xmlversion="1.0"encoding="UTF-8"?>
  2. <viewcache>
  3. <areas>
  4. <area>
  5. <id>1098</id>
  6. <parentId>1001</parentId>
  7. <areaType>province</areaType>
  8. <name>北京</name>
  9. <ordering>1867</ordering>
  10. </area>
  11. <area>
  12. <id>1099</id>
  13. <parentId>1098</parentId>
  14. <areaType>capital</areaType>
  15. <name>北京</name>
  16. <ordering>1868</ordering>
  17. <phoneArea>010</phoneArea>
  18. </area>
  19. <area>
  20. <id>4476</id>
  21. <parentId>1099</parentId>
  22. <areaType>county</areaType>
  23. <name>北京市朝阳区</name>
  24. <ordering>1869</ordering>
  25. <phoneArea>010</phoneArea>
  26. </area>
  27. <area>
  28. <id>4477</id>
  29. <parentId>1099</parentId>
  30. <areaType>county</areaType>
  31. <name>北京市崇文区</name>
  32. <ordering>1870</ordering>
  33. <phoneArea>010</phoneArea>
  34. </area>
  35. <area>
  36. <id>4478</id>
  37. <parentId>1099</parentId>
  38. <areaType>county</areaType>
  39. <name>北京市大兴区</name>
  40. <ordering>1871</ordering>
  41. <phoneArea>010</phoneArea>
  42. </area>
  43. </areas>
  44. </viewcache>

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

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

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

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

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

[java] view plain copy
  1. publicclassArea{
  2. privateintid;
  3. privateStringname;
  4. privateStringareaType;
  5. privateintparentId;
  6. privateintordering;
  7. privateStringzip;
  8. privateStringphoneArea;
  9. publicintgetOrdering(){
  10. returnordering;
  11. }
  12. publicvoidsetOrdering(intordering){
  13. this.ordering=ordering;
  14. }
  15. publicStringgetAreaType(){
  16. returnareaType;
  17. }
  18. publicvoidsetAreaType(StringareaType){
  19. this.areaType=areaType;
  20. }
  21. publicintgetId(){
  22. returnid;
  23. }
  24. publicvoidsetId(intid){
  25. this.id=id;
  26. }
  27. publicStringgetName(){
  28. returnname;
  29. }
  30. publicvoidsetName(Stringname){
  31. this.name=name;
  32. }
  33. publicintgetParentId(){
  34. returnparentId;
  35. }
  36. publicvoidsetParentId(intparentId){
  37. this.parentId=parentId;
  38. }
  39. publicStringgetZip(){
  40. returnzip;
  41. }
  42. publicvoidsetZip(Stringzip){
  43. this.zip=zip;
  44. }
  45. publicStringgetPhoneArea(){
  46. returnphoneArea;
  47. }
  48. publicvoidsetPhoneArea(StringphoneArea){
  49. this.phoneArea=phoneArea;
  50. }
  51. }

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

[java] view plain copy
  1. publicclassViewCache{
  2. privateListareaList=newArrayList();
  3. publicListgetAreaList(){
  4. returnareaList;
  5. }
  6. publicvoidsetAreaList(ListareaList){
  7. this.areaList=areaList;
  8. }
  9. //供Digester调用的方法
  10. publicvoidaddArea(Areaarea){
  11. this.areaList.add(area);
  12. }
  13. }

创建一个类AreaDigester,对xml文件进行解析:

[java] view plain copy
    public class AreaDigester {  
          
        public ViewCache digester() throws Exception {  
            Digester digester = new Digester();  
            digester.setValidating(false);  
            digester.addObjectCreate("viewcache/areas",ViewCache.class);  
            // 指明匹配模式和要创建的类   
            digester.addObjectCreate("viewcache/areas/area",Area.class);  
            // 设置对象属性,与xml文件对应,不设置则是默认  
            digester.addBeanPropertySetter("viewcache/areas/area/id","id");  
            digester.addBeanPropertySetter("viewcache/areas/area/parentId","parentId");  
            digester.addBeanPropertySetter("viewcache/areas/area/name","name");  
            digester.addBeanPropertySetter("viewcache/areas/area/areaType","areaType");  
            digester.addBeanPropertySetter("viewcache/areas/area/ordering","ordering");  
            digester.addBeanPropertySetter("viewcache/areas/area/zip","zip");  
            digester.addBeanPropertySetter("viewcache/areas/area/phoneArea","phoneArea");  
            // 当移动到下一个标签中时的动作  
            digester.addSetNext("viewcache/areas/area","addArea");  
              
            ViewCache vc = null;  
            try {  

                File file = new File("viewcache.xml");
          BufferedReader read = new BufferedReader(new InputStreamReader(new FileInputStream(file)));
          StringBuffer sb = new StringBuffer();
          String content = "";
          while((content=read.readLine()) != null){
             sb.append(content);
          }
                vc = (ViewCache) digester.parse(new StringReader(sb.toString()));  
            } catch (IOException e) {  
                throw new Exception(e);  
            } catch (SAXException e) {  
                throw new Exception(e);  
            }  
            return vc;  
        }  

    }  







调用AreaDigester的digester方法,即可把解析后的所有地址对象,存放在ViewCache的list中。

例子2:

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

[xhtml] view plain copy
  1. <?xmlversion="1.0"encoding="UTF-8"?>
  2. <libraryname="alibaba图书馆">
  3. <booktitle="thinkinginjava"author="xxx">
  4. <chapter>
  5. <no>第一章</no>
  6. <caption>第一章的标题</caption>
  7. </chapter>
  8. <chapter>
  9. <no>第二章</no>
  10. <caption>第二章的标题</caption>
  11. </chapter>
  12. </book>
  13. <booktitle="effectivejava"author="yyy">
  14. <chapter>
  15. <no>第一章</no>
  16. <caption>第一章的标题</caption>
  17. </chapter>
  18. </book>
  19. </library>

Library类如下:

[java] view plain copy
  1. publicclassLibrary{
  2. privateStringname;
  3. privateList<Book>bookList=newArrayList<Book>();
  4. publicStringgetName(){
  5. returnname;
  6. }
  7. publicvoidsetName(Stringname){
  8. this.name=name;
  9. }
  10. publicList<Book>getBookList(){
  11. returnbookList;
  12. }
  13. publicvoidaddBook(Bookbook){
  14. bookList.add(book);
  15. }
  16. }

Book类如下:

[java] view plain copy
  1. publicclassBook{
  2. privateStringtitle;
  3. privateStringauthor;
  4. privateList<Chapter>chapters=newArrayList<Chapter>();
  5. /**
  6. *这个方法,用来演示xml的解析时用的另一种方式
  7. *@paramtitle
  8. *@paramauthor
  9. */
  10. publicvoidsetBookInfo(Stringtitle,Stringauthor){
  11. this.title=title;
  12. this.author=author;
  13. }
  14. publicvoidaddChapter(Chapterchapter){
  15. this.chapters.add(chapter);
  16. }
  17. publicStringgetTitle(){
  18. returntitle;
  19. }
  20. publicvoidsetTitle(Stringtitle){
  21. this.title=title;
  22. }
  23. publicStringgetAuthor(){
  24. returnauthor;
  25. }
  26. publicvoidsetAuthor(Stringauthor){
  27. this.author=author;
  28. }
  29. publicList<Chapter>getChapters(){
  30. returnchapters;
  31. }
  32. publicvoidsetChapters(List<Chapter>chapters){
  33. this.chapters=chapters;
  34. }
  35. }

Chapter类如下:

[java] view plain copy
  1. publicclassChapter{
  2. privateStringno;
  3. privateStringcaption;
  4. publicStringgetNo(){
  5. returnno;
  6. }
  7. publicvoidsetNo(Stringno){
  8. this.no=no;
  9. }
  10. publicStringgetCaption(){
  11. returncaption;
  12. }
  13. publicvoidsetCaption(Stringcaption){
  14. this.caption=caption;
  15. }
  16. }

解析xml的类如下:

[java] view plain copy
  1. publicclassMainTest{
  2. /**
  3. *@paramargs
  4. */
  5. publicstaticvoidmain(String[]args){
  6. //建立一个Digester对象
  7. Digesterdigester=newDigester();
  8. //指定它不要用DTD验证XML文档的合法性——这是因为我们没有为XML文档定义DTD
  9. digester.setValidating(false);
  10. //从library标签开始解析,并新建一个Library对象做为根对象
  11. digester.addObjectCreate("library",Library.class);
  12. //根据library标签属性值设置对象的属性,一次可以设置多个属性
  13. digester.addSetProperties("library");
  14. //也可以用下面的方法,指定propertyName
  15. //digester.addSetProperties("library","name","name");
  16. //-----第1层元素开始
  17. digester.addObjectCreate("library/book",Book.class);
  18. //digester.addSetProperties("library/book");
  19. //可以用以下三条语句代替
  20. digester.addCallMethod("library/book","setBookInfo",2);
  21. digester.addCallParam("library/book",0,"title");
  22. digester.addCallParam("library/book",1,"author");
  23. /**
  24. *addCallParam(Stringrule,intparaIndex,StringattributeName)
  25. *该方法与addCallMethod配合使用
  26. *intparaIndex:表明需要填充的方法形参序号,从0开始,方法由addCallMethod指定
  27. *StringattributeName:指定标签属性名称
  28. */
  29. //-----第2层元素开始
  30. digester.addObjectCreate("library/book/chapter",Chapter.class);
  31. /**addBeanPropertySetter()是将子节点转换为对象的属性,这个方法还可以有第二个参数,当对象的属性名和子节点的名字不一样时用来指定对象的属性名
  32. 该方法的作用及使用方法类似于addSetProperties,只不过它是用Stringrule规则所指定标签的值(而不是标签的属性)来调用对象的setter*/
  33. digester.addBeanPropertySetter("library/book/chapter/no");
  34. //digester.addBeanPropertySetter("library/book/chapter/no","no");
  35. /**addCallMethod(Stringrule,StringmethodName,intparaNumber)方法
  36. *同样是设置对象的属性,但是方式更加灵活,不需要对象具有setter
  37. *当paraNumber=0时,可以单独使用(表明为标签的值来调用),不然需要配合addCallParam方法
  38. */
  39. //digester.addBeanPropertySetter("library/book/chapter/caption");
  40. //下面的方法,可以用来代替上一句,作用是一样的
  41. digester.addCallMethod("library/book/chapter/caption","setCaption",0);
  42. //addSetNext()是说在再次遇到匹配节点后,调用当前对象(Chapter类的对象)的父对象(Book类的对象)的方法,方法参数是当前层元素的对象
  43. digester.addSetNext("library/book/chapter","addChapter");
  44. //-----第2层元素结束
  45. digester.addSetNext("library/book","addBook");
  46. //-----第1层元素结束
  47. try{
  48. //解析XML文件,并得到ROOT元素
  49. Librarylibrary=(Library)digester.parse(MainTest.class.getResourceAsStream("books.xml"));
  50. System.out.println("图书馆:"+library.getName());
  51. System.out.println("共藏书:"+library.getBookList().size()+"本");
  52. System.out.println("*****************************");
  53. for(Bookbook:library.getBookList()){
  54. System.out.println("书名:"+book.getTitle()+"作者:"+book.getAuthor());
  55. System.out.println("------------------------------");
  56. //显示章节
  57. System.out.println("共"+book.getChapters().size()+"章");
  58. for(Chapterchapter:book.getChapters()){
  59. System.out.println(chapter.getNo()+":"+chapter.getCaption());
  60. }
  61. System.out.println("------------------------------");
  62. }
  63. }catch(IOExceptione){
  64. e.printStackTrace();
  65. }catch(SAXExceptione){
  66. e.printStackTrace();
  67. }
  68. }
  69. }

例子3:

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文件,可以知道有哪些标签可以使用)

[xhtml] view plain copy
  1. <?xmlversion="1.0"encoding="UTF-8"?>
  2. <!DOCTYPEdigester-rulesPUBLIC
  3. "-//JakartaApache//DTDdigester-rulesXMLV1.0//EN"
  4. "digester-rules.dtd">
  5. <digester-rules>
  6. <object-create-rulepattern="library"classname="com.alibaba.chj.digester.Library"/>
  7. <set-properties-rulepattern="library">
  8. <aliasattr-name="name"prop-name="name"/>
  9. </set-properties-rule>
  10. <patternvalue="library/book">
  11. <object-create-ruleclassname="com.alibaba.chj.digester.Book"/>
  12. <set-properties-rule/>
  13. <patternvalue="chapter">
  14. <object-create-ruleclassname="com.alibaba.chj.digester.Chapter"/>
  15. <bean-property-setter-rulepattern="no"propertyname="no"/>
  16. <bean-property-setter-rulepattern="caption"propertyname="caption"/>
  17. <set-next-rulemethodname="addChapter"/>
  18. </pattern>
  19. <set-next-rulemethodname="addBook"/>
  20. </pattern>
  21. </digester-rules>

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

[java] view plain copy
  1. publicclassMainTest{
  2. /**
  3. *@paramargs
  4. */
  5. publicstaticvoidmain(String[]args){
  6. try{
  7. Digesterdigester=DigesterLoader.createDigester(DigesterXmlRuleTest.class.getResource("books-rule.xml"));
  8. Librarylibrary=(Library)digester.parse(DigesterXmlRuleTest.class.getResourceAsStream("books.xml"));
  9. System.out.println("图书馆:"+library.getName());
  10. System.out.println("共藏书:"+library.getBookList().size()+"本");
  11. System.out.println("*****************************");
  12. for(Bookbook:library.getBookList()){
  13. System.out.println("书名:"+book.getTitle()+"作者:"+book.getAuthor());
  14. System.out.println("------------------------------");
  15. //显示章节
  16. System.out.println("共"+book.getChapters().size()+"章");
  17. for(Chapterchapter:book.getChapters()){
  18. System.out.println(chapter.getNo()+":"+chapter.getCaption());
  19. }
  20. System.out.println("------------------------------");
  21. }
  22. }catch(IOExceptione){
  23. e.printStackTrace();
  24. }catch(SAXExceptione){
  25. e.printStackTrace();
  26. }
  27. }
  28. }

用于规则放在xml文件中,所以解析的类,显得更加简洁一些。

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读