Digester解析xml文件

刚刚学了一下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. <?xml version="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. public class Area {
  2. private int    id;
  3. private String name;
  4. private String areaType;
  5. private int    parentId;
  6. private int    ordering;
  7. private String zip;
  8. private String phoneArea;
  9. public int getOrdering() {
  10. return ordering;
  11. }
  12. public void setOrdering(int ordering) {
  13. this.ordering = ordering;
  14. }
  15. public String getAreaType() {
  16. return areaType;
  17. }
  18. public void setAreaType(String areaType) {
  19. this.areaType = areaType;
  20. }
  21. public int getId() {
  22. return id;
  23. }
  24. public void setId(int id) {
  25. this.id = id;
  26. }
  27. public String getName() {
  28. return name;
  29. }
  30. public void setName(String name) {
  31. this.name = name;
  32. }
  33. public int getParentId() {
  34. return parentId;
  35. }
  36. public void setParentId(int parentId) {
  37. this.parentId = parentId;
  38. }
  39. public String getZip() {
  40. return zip;
  41. }
  42. public void setZip(String zip) {
  43. this.zip = zip;
  44. }
  45. public String getPhoneArea() {
  46. return phoneArea;
  47. }
  48. public void setPhoneArea(String phoneArea) {
  49. this.phoneArea = phoneArea;
  50. }
  51. }

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

[java] view plain copy

  1. public class ViewCache {
  2. private List areaList             = new ArrayList();
  3. public List getAreaList() {
  4. return areaList;
  5. }
  6. public void setAreaList(List areaList) {
  7. this.areaList = areaList;
  8. }
  9. // 供Digester调用的方法
  10. public void addArea(Area area) {
  11. this.areaList.add(area);
  12. }
  13. }

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

[java] view plain copy

  1. public class AreaDigester {
  2. public ViewCache digester() throws Exception {
  3. Digester digester = new Digester();
  4. digester.setValidating(false);
  5. digester.addObjectCreate("viewcache/areas", ViewCache.class);
  6. // 指明匹配模式和要创建的类
  7. digester.addObjectCreate("viewcache/areas/area", Area.class);
  8. // 设置对象属性,与xml文件对应,不设置则是默认
  9. digester.addBeanPropertySetter("viewcache/areas/area/id", "id");
  10. digester.addBeanPropertySetter("viewcache/areas/area/parentId", "parentId");
  11. digester.addBeanPropertySetter("viewcache/areas/area/name", "name");
  12. digester.addBeanPropertySetter("viewcache/areas/area/areaType", "areaType");
  13. digester.addBeanPropertySetter("viewcache/areas/area/ordering", "ordering");
  14. digester.addBeanPropertySetter("viewcache/areas/area/zip", "zip");
  15. digester.addBeanPropertySetter("viewcache/areas/area/phoneArea", "phoneArea");
  16. // 当移动到下一个标签中时的动作
  17. digester.addSetNext("viewcache/areas/area", "addArea");
  18. ViewCache vc = null;
  19. try {
  20. vc = (ViewCache) digester.parse("viewcache.xml");
  21. } catch (IOException e) {
  22. throw new Exception(e);
  23. } catch (SAXException e) {
  24. throw new Exception(e);
  25. }
  26. return vc;
  27. }
  28. }

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

例子2:

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

[xhtml] view plain copy

  1. <?xml version="1.0" encoding="UTF-8" ?>
  2. <library name="alibaba图书馆">
  3. <book title ="thinking in java"  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. <book title="effective java"  author="yyy">
  14. <chapter>
  15. <no>第一章</no>
  16. <caption>第一章的标题</caption>
  17. </chapter>
  18. </book>
  19. </library>

Library类如下:

[java] view plain copy

  1. public class Library {
  2. private String name;
  3. private List<Book> bookList = new ArrayList<Book>();
  4. public String getName() {
  5. return name;
  6. }
  7. public void setName(String name) {
  8. this.name = name;
  9. }
  10. public List<Book> getBookList() {
  11. return bookList;
  12. }
  13. public void addBook(Book book) {
  14. bookList.add(book);
  15. }
  16. }

Book类如下:

[java] view plain copy

  1. public class Book {
  2. private String        title;
  3. private String        author;
  4. private List<Chapter> chapters = new ArrayList<Chapter>();
  5. /**
  6. * 这个方法,用来演示xml的解析时用的另一种方式
  7. * @param title
  8. * @param author
  9. */
  10. public void setBookInfo(String title, String author) {
  11. this.title = title;
  12. this.author = author;
  13. }
  14. public void addChapter(Chapter chapter) {
  15. this.chapters.add(chapter);
  16. }
  17. public String getTitle() {
  18. return title;
  19. }
  20. public void setTitle(String title) {
  21. this.title = title;
  22. }
  23. public String getAuthor() {
  24. return author;
  25. }
  26. public void setAuthor(String author) {
  27. this.author = author;
  28. }
  29. public List<Chapter> getChapters() {
  30. return chapters;
  31. }
  32. public void setChapters(List<Chapter> chapters) {
  33. this.chapters = chapters;
  34. }
  35. }

Chapter类如下:

[java] view plain copy

  1. public class Chapter {
  2. private String no;
  3. private String caption;
  4. public String getNo() {
  5. return no;
  6. }
  7. public void setNo(String no) {
  8. this.no = no;
  9. }
  10. public String getCaption() {
  11. return caption;
  12. }
  13. public void setCaption(String caption) {
  14. this.caption = caption;
  15. }
  16. }

解析xml的类如下:

[java] view plain copy

  1. public class MainTest {
  2. /**
  3. * @param args
  4. */
  5. public static void main(String[] args) {
  6. // 建立一个Digester对象
  7. Digester digester = new Digester();
  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(String rule, int  paraIndex,String attributeName)
  25. * 该方法与addCallMethod配合使用
  26. * int paraIndex:表明需要填充的方法形参序号,从 0 开始,方法由addCallMethod指定
  27. * String attributeName:指定标签属性名称
  28. */
  29. // -----第2层元素开始
  30. digester.addObjectCreate("library/book/chapter", Chapter.class);
  31. /** addBeanPropertySetter()是将子节点转换为对象的属性,这个方法还可以有第二个参数,当对象的属性名和子节点的名字不一样时用来指定对象的属性名
  32. 该方法的作用及使用方法类似于addSetProperties,只不过它是用String rule规则所指定标签的值(而不是标签的属性)来调用对象的setter*/
  33. digester.addBeanPropertySetter("library/book/chapter/no");
  34. // digester.addBeanPropertySetter("library/book/chapter/no", "no");
  35. /** addCallMethod(String rule,String methodName, int  paraNumber) 方法
  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. Library library = (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 (Book book : library.getBookList()) {
  54. System.out.println(" 书名: " + book.getTitle() + "        作者: " + book.getAuthor());
  55. System.out.println(" ------------------------------ ");
  56. // 显示章节
  57. System.out.println(" 共 " + book.getChapters().size() + " 章 ");
  58. for (Chapter chapter : book.getChapters()) {
  59. System.out.println(chapter.getNo() + ": " + chapter.getCaption());
  60. }
  61. System.out.println(" ------------------------------ ");
  62. }
  63. } catch (IOException e) {
  64. e.printStackTrace();
  65. } catch (SAXException e) {
  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. <?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类的代码,修改为:

[java] view plain copy

  1. public class MainTest {
  2. /**
  3. * @param args
  4. */
  5. public static void main(String[] args) {
  6. try {
  7. Digester digester = DigesterLoader.createDigester(DigesterXmlRuleTest.class.getResource("books-rule.xml"));
  8. Library library = (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 (Book book : library.getBookList()) {
  13. System.out.println(" 书名: " + book.getTitle() + "        作者: " + book.getAuthor());
  14. System.out.println(" ------------------------------ ");
  15. // 显示章节
  16. System.out.println(" 共 " + book.getChapters().size() + " 章 ");
  17. for (Chapter chapter : book.getChapters()) {
  18. System.out.println(chapter.getNo() + ": " + chapter.getCaption());
  19. }
  20. System.out.println(" ------------------------------ ");
  21. }
  22. } catch (IOException e) {
  23. e.printStackTrace();
  24. } catch (SAXException e) {
  25. e.printStackTrace();
  26. }
  27. }
  28. }

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

原文地址:https://www.cnblogs.com/hanguocai/p/8250973.html

时间: 2024-08-27 05:37:52

Digester解析xml文件的相关文章

使用XML序列化器生成XML文件和利用pull解析XML文件

首先,指定XML格式,我指定的XML格式如下: <?xml version='1.0' encoding='utf-8' standalone='yes' ?> <message> <sms> <body> 陈驰0 </body> <date> 1462162910995 </date> <address> 1380 </address> <type> 1 </type> &

解析xml文件的几个步骤

1.生成xml文件的解析器 XmlPullParser parser = Xml.newPullParser(); 2.设置解析器读取流对象的编码格式 parser.setInput(is, "utf-8"); 3.设置解析xml文件之后要存储的位置 List<WeatherInfo> weatherInfo = null; WeatherInfo info = null; 4.定义解析器解析到的事件类型 int type = parser.getEventType();

JS解析XML文件和XML字符串

JS解析XML文件 <script type='text/javascript'>    loadXML = function(xmlFile){        var xmlDoc=null;        //判断浏览器的类型        //支持IE浏览器        if(!window.DOMParser && window.ActiveXObject){            var xmlDomVersions = ['MSXML.2.DOMDocument.

Php 解析XML文件

Php 解析XML文件 Php 解析XML文件,仅供学习参考!示例代码如下: <?php header("Content-type: text/html; charset=utf-8"); if(!isset($_GET["_u"])){ echo "<script>javascript:alert('请勿非法访问!');window.history.back();</script>"; exit(); } $url

SAX解析XML文件

SAX是Simple API for XML的缩写,它并不是由W3C官方所提出的标准.SAX是一种轻量型的方法,不像DOM解析时,把XML文档全部载入内存中,在PC上操作,Dom还有 优势,但在手机中端上则无优势,因为手机内存和硬件都比不上PC强.使用 SAX 是比较安全的,并且 Android 提供了一种传统的 SAX 使用方法,以及一个便捷的 SAX 包装器.SAX采用基于事件驱动的处理方式,它将XML文档转换成一系列的事件,由单独的事件处理器来决定如何处理. 在SAX接口中,事件源是org

Android开发学习---使用XmlPullParser解析xml文件

Android中解析XML的方式主要有三种:sax,dom和pull关于其内容可参考:http://blog.csdn.net/liuhe688/article/details/6415593 本文将主要介绍pull解析器解析xml文件,环境为ubuntu 12.04+ intelij 13.1 + android sdk 2.1 一.创建一个XML项目,步骤如下: 二.解析一个xml文件: assets/person.xml <?xml version="1.0" encodi

【Android进阶】解析XML文件之使用DOM解析器

在前面的文章中,介绍了使用SAX解析器对XML文件进行解析,SAX解析器的优点就是占用内存小.这篇文章主要介绍使用DOM解析器对XML文件进行解析.DOM解析器的优点可能是理解起来比较的直观,当然,每个人对不同的解析方法可能有不同的喜好.但是DOM解析器有个比较大的缺点,就是占用内存比较多,在Android中的XML解析中,还是更推荐其他的解析方式. 下面介绍使用DOM解析器对XML进行解析. 下面是我们需要解析的xml文件 <?xml version="1.0" encodin

Dom方法,解析XML文件

Dom方法,解析XML文件的基本操作 1 package com.demo.xml.jaxp; 2 3 import java.io.IOException; 4 5 import javax.xml.parsers.DocumentBuilder; 6 import javax.xml.parsers.DocumentBuilderFactory; 7 import javax.xml.parsers.ParserConfigurationException; 8 import javax.x

解析xml文件

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>js 解析xml文件</title> </head> <body> <script type="text/javascript"> var xmlDoc=document.implementation.