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

Digester解析xml文件

发布时间:2020-12-16 05:45:15 所属栏目:百科 来源:网络整理
导读:原文:http://www.jb51.cc/article/p-dthhuuou-tb.html 刚刚学了一下Digester如何解析xml文件,所以记录下来,方便以后查看。 一般用来读取xml文件的工具包有DOM、SAX和JDOM等,但用过的人都知道,它们属于比较底层的API,写起来代码量很大,而且如果修改了x

原文:http://www.52php.cn/article/p-dthhuuou-tb.html


刚刚学了一下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. </>
  6. >

例子1:

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

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

view plain copy
    <?xmlversion="1.0"encoding="UTF-8"?>
  1. viewcache>
  2. areasareaid>1098parentId>1001areaType>province>北京ordering>1867>1099>capital>1868phoneArea>010>4476>county>北京市朝阳区>1869>4477>北京市崇文区>1870>4478>北京市大兴区>1871 此xml文件分3层结构,分别为:

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

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

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

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

    [java] copy
      publicclassArea{
    1. privateintid;
    2. privateStringname;
    3. privateStringareaType;
    4. intparentId;
    5. intordering;
    6. privateStringzip;
    7. privateStringphoneArea;
    8. intgetOrdering(){
    9. returnordering;
    10. }
    11. voidsetOrdering(intordering){
    12. this.ordering=ordering;
    13. }
    14. publicStringgetAreaType(){
    15. returnareaType;
    16. voidsetAreaType(StringareaType){
    17. this.areaType=areaType;
    18. intgetId(){
    19. returnid;
    20. voidsetId(intid){
    21. this.id=id;
    22. publicStringgetName(){
    23. returnname;
    24. voidsetName(Stringname){
    25. this.name=name;
    26. intgetParentId(){
    27. returnparentId;
    28. voidsetParentId(intparentId){
    29. this.parentId=parentId;
    30. publicStringgetZip(){
    31. returnzip;
    32. voidsetZip(Stringzip){
    33. this.zip=zip;
    34. publicStringgetPhoneArea(){
    35. returnphoneArea;
    36. voidsetPhoneArea(StringphoneArea){
    37. this.phoneArea=phoneArea;
    38. }

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

    copy

      classViewCache{
    1. privateListareaList=newArrayList();
    2. publicListgetAreaList(){
    3. returnareaList;
    4. voidsetAreaList(ListareaList){
    5. this.areaList=areaList;
    6. //供Digester调用的方法
    7. voidaddArea(Areaarea){
    8. this.areaList.add(area);
    9. }

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

    copy
      classAreaDigester{
    1. publicViewCachedigester()throwsException{
    2. Digesterdigester=newDigester();
    3. digester.setValidating(false);
    4. digester.addObjectCreate("viewcache/areas",ViewCache.class);
    5. //指明匹配模式和要创建的类
    6. digester.addObjectCreate("viewcache/areas/area",Area.//设置对象属性,与xml文件对应,不设置则是默认
    7. digester.addBeanPropertySetter("viewcache/areas/area/id","id");
    8. digester.addBeanPropertySetter("viewcache/areas/area/parentId","parentId");
    9. digester.addBeanPropertySetter("viewcache/areas/area/name","name");
    10. digester.addBeanPropertySetter("viewcache/areas/area/areaType","areaType");
    11. digester.addBeanPropertySetter("viewcache/areas/area/ordering","ordering");
    12. digester.addBeanPropertySetter("viewcache/areas/area/zip","zip");
    13. digester.addBeanPropertySetter("viewcache/areas/area/phoneArea","phoneArea");
    14. //当移动到下一个标签中时的动作
    15. digester.addSetNext("viewcache/areas/area","addArea");
    16. ViewCachevc=null;
    17. try{
    18. vc=(ViewCache)digester.parse("viewcache.xml");
    19. }catch(IOExceptione){
    20. thrownewException(e);
    21. catch(SAXExceptione){
    22. returnvc;
    23. }

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

    例子2:

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

    copy

      libraryname="alibaba图书馆"booktitle="thinkinginjava"author="xxx"chapterno>第一章caption>第一章的标题>第二章>第二章的标题bookbooktitle="effectivejava"author="yyy"library Library类如下:

      copy

        classLibrary{
      1. privateStringname;
      2. privateList<Book>bookList=newArrayList<Book>();
      3. voidsetName(Stringname){
      4. this.name=name;
      5. publicList<Book>getBookList(){
      6. returnbookList;
      7. voidaddBook(Bookbook){
      8. bookList.add(book);
      9. Book类如下:

        copy

          classBook{
        1. privateStringtitle;
        2. privateStringauthor;
        3. privateList<Chapter>chapters=newArrayList<Chapter>();
        4. /**
        5. *这个方法,用来演示xml的解析时用的另一种方式
        6. *@paramtitle
        7. *@paramauthor
        8. */
        9. voidsetBookInfo(Stringtitle,Stringauthor){
        10. this.title=title;
        11. this.author=author;
        12. voidaddChapter(Chapterchapter){
        13. this.chapters.add(chapter);
        14. publicStringgetTitle(){
        15. returntitle;
        16. voidsetTitle(Stringtitle){
        17. this.title=title;
        18. publicStringgetAuthor(){
        19. returnauthor;
        20. voidsetAuthor(Stringauthor){
        21. publicList<Chapter>getChapters(){
        22. returnchapters;
        23. voidsetChapters(List<Chapter>chapters){
        24. this.chapters=chapters;
        25. Chapter类如下:

          copy

            classChapter{
          1. privateStringno;
          2. privateStringcaption;
          3. publicStringgetNo(){
          4. returnno;
          5. voidsetNo(Stringno){
          6. this.no=no;
          7. publicStringgetCaption(){
          8. returncaption;
          9. voidsetCaption(Stringcaption){
          10. this.caption=caption;
          11. }

          解析xml的类如下:

          copy

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

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

            copy

              <!DOCTYPEdigester-rulesPUBLIC
            1. "-//JakartaApache//DTDdigester-rulesXMLV1.0//EN"
            2. "digester-rules.dtd"digester-rulesobject-create-rulepattern="library"classname="com.alibaba.chj.digester.Library"/>
            3. set-properties-rulepattern="library"aliasattr-name="name"prop-name="name"set-properties-rulepatternvalue="library/book"object-create-ruleclassname="com.alibaba.chj.digester.Book"/>
            4. set-properties-rulepatternvalue="chapter"object-create-ruleclassname="com.alibaba.chj.digester.Chapter"bean-property-setter-rulepattern="no"propertyname="no"bean-property-setter-rulepattern="caption"propertyname="caption"set-next-rulemethodname="addChapter"patternset-next-rulemethodname="addBook" 解析xml类的代码,修改为:

              copy

                Digesterdigester=DigesterLoader.createDigester(DigesterXmlRuleTest.class.getResource("books-rule.xml"));
              1. Librarylibrary=(Library)digester.parse(DigesterXmlRuleTest. 用于规则放在xml文件中,所以解析的类,显得更加简洁一些。

                Digester FAQ:http://wiki.apache.org/commons/Digester/FAQ

                (编辑:李大同)

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

    推荐文章
      热点阅读