Digester类如何将XML映射成Java类



Digester类如何将XML映射成Java类,common-digester如何解析xml文件,简化XML的处理。它为Apache Commons库中的一个jar包:common-digester包

引用:import org.apache.commons.digester.Digester;

Digester类通过模式(pattern)和规则来处理XML文档。其中的模式必须匹配XML元素,即XML文档树中的节点名和位置。Digester匹配模式的语法类似XPath的匹配模式,如模式catalog匹配最顶层<catalog>,模式catalog/book匹配<catalog>节点的子节点<book>。所有的匹配都是绝对路径,即所有的路径都是从根元素开始向下被指定的,有一个例外,几句是包含通配符”*”的匹配模式,如模式*/name将匹配XML文档中的任何<name>节点。

为解析XML文档,要建立一个org.apache.commons.digester.Digester类实例,而且进行配置,指定有关的模式以及规则,最后把XML文件的引用传入parse方法。Digester解析XML文档,依次读入XML文件,采用堆栈残存储实例,从父节点开始读入,创建父节点对应的实例压入堆栈,当读到结束标志时弹出堆栈,读到子节点,创建子节点对应实例压入堆栈,因此可以看出次栈顶实例是栈顶实例的父节点,同级的节点点之间没有关联关系。

以userdatabase.xml文件为例,使用Digester实例的常用方法解析xml文件

  1. <?xml version=”1.0″ encoding=”UTF-8?>
  2. <database>
  3.     <user userName=”guest” password=”guest”>
  4.     </user>
  5. </database>

1.Digester类的方法之addObjectCreate(String rule,Class class)

设置节点与Java对象的映射规则,rule指定节点的筛选规则,class设置映射对象。SAX解析时,遇到rule指定的节节点,会创建一个class实例放入堆栈中。

比如:digester.addObectCreate(“database/user”,”com.model.UserBean”).解析遇到user节点时,会创建一个UserBean实例并放入堆栈中。

2.Digester类的方法之addSetProperties(String rule)

设置节点的属性设置规则。当解析遇到符合rule的节点时,根据属性列表中的属性值对,使用Java反射机制使用标准的JavaBean方法设置栈顶对象实例;

比如:digester.addSetProperties(“database/user”),解析遇到user节点时,会获取键值对 userName=guest,password=guest,获得栈顶的UserBean对象,设置实例的userName、password属性;

3.Digester类的方法之addBeanPropertySetter(String rule)

该方法的作用及使用方法类似于addSetProperties,只不过它是用rule所指定的标签来调用对象的setter。

4.addSetNext(String rule,String methodName)

设置当前rule节点与父节点的调用规则,当遇到rule节点时,调用堆栈中的次栈顶元素调用methodName方法。将栈顶元素作为次顶元素指定方法的输入参数。

比如:digester.addSetNext(“database/user”,”addUser”),调用database实例的addUser,user为参数

5.Digester类的方法之addCallMethod(String rule,String methodName,int paraNumber)

该方法同样设置对象的属性,但更加灵活,不需要对象具有setter

根据rule规则指定的属性,调用对象的methodName方法,paraNumber参数是表示方法需要的参数个数,当paraNumber=0时,可以单独使用,不然需要配合addCallParam方法


比如:digester.addCallMethod(“database/user/uerName”,”setUserName”,0);

6.addCallParam(String rule,int paraIndex,String attributeName)

该方法与addCallMethod配合使用,根据rule指定的标签属性来调用方法

paraIndex表明需要填充的方法形参序号,从0开始,方法由addCallMethdo指定,attributeName指定标签属性名;

使用注意事项:

1.Digester类调用的顺序,必须与XML数据文件绝对一致;
2.Digester类依赖于JavaBean规范,类必须符合规范;
3.XML文件中标签/属性的名称必须与Bean中的一致(包括大小写);

以下是common-digester解析xml的源码实例:

版本:digester2.0+   beanutils 1.8+  logging1.1+

<?xml version=”1.0″ encoding=”UTF-8″?>
<menu>
<root title=”website”>
<node title=”qq” url=”www.qq.com”></node>
<node title=”163″ url=”www.163.com”></node>
</root>
</menu>

Menu -> root -> node

package com.taobao.digester;

import java.util.ArrayList;
import java.util.List;

public class Menu {
private List<Root> roots;

public Menu(){
roots = new ArrayList<Root>();
}

public void addRoot(Root root) {
roots.add(root);
}

@Override
public String toString() {
return “Menu:<” +roots+ “>”;
}
}

 

  1. package com.taobao.digester;  
  2. import java.util.ArrayList;
  3. import java.util.List;
  4. public class Root {
  5.     private String title;
  6.     private List<Node> nodes;
  7.     public Root(){
  8.         nodes = new ArrayList<Node>();
  9.     }
  10.     public String getTitle() {
  11.         return title;
  12.     }
  13.     public void setTitle(String title) {
  14.         this.title = title;
  15.     }
  16.     public void addNode(Node node){
  17.         nodes.add(node);
  18.     }
  19.     @Override
  20.     public String toString() {
  21.         return ”Root:<”+nodes+”>, ”+title;
  22.     }
  23. }

 

  1. <pre name=”code” class=”java”>package com.taobao.digester;
  2. public class Node {
  3.     private String title;
  4.     private String url;
  5.     public String getTitle() {
  6.         return title;
  7.     }
  8.     public void setTitle(String title) {
  9.         this.title = title;
  10.     }
  11.     public String getUrl() {
  12.         return url;
  13.     }
  14.     public void setUrl(String url) {
  15.         this.url = url;
  16.     }
  17.     @Override
  18.     public String toString() {
  19.         return ”Node: title=”+title+”, url:”+url;
  20.     }
  21. }
  22. </pre><br>
  23. <p></p>
  24. <pre></pre>
  25. <p></p>
  26. <p><br>
  27. </p>
  28. test:
  29. <p></p><pre name=”code” class=”java”>package com.taobao.digester;
  30. import java.io.File;
  31. import java.io.IOException;
  32. import org.apache.commons.digester.Digester;
  33. import org.xml.sax.SAXException;
  34. public class Test {
  35.      public static void main(String[] args) throws IOException, SAXException {
  36.          Digester digester = new Digester();
  37.          digester.setValidating(false);
  38.          digester.addObjectCreate(“menu”, com.taobao.digester.Menu.class);
  39.          digester.addObjectCreate(“menu/root”, com.taobao.digester.Root.class);
  40.          digester.addSetProperties(“menu/root”, ”title”, ”title”);
  41.          digester.addSetNext(“menu/root”, ”addRoot”);  //addSetNext方法很重要 决定了加入上层的方法
  42.                                                        //还要注意的一点是这个方法在上层的menu中
  43.          digester.addObjectCreate(“menu/root/node”, com.taobao.digester.Node.class);
  44.          digester.addSetProperties(“menu/root/node”, ”title”, ”title”);  //menu/root/node 有两个属性 所有加两次
  45.          digester.addSetProperties(“menu/root/node”, ”url”, ”url”);
  46.          digester.addSetNext(“menu/root/node”, ”addNode”);
  47.          Menu menu = (Menu)digester.parse(new File(“e:/NewFile.xml”));
  48.          System.out.println(menu);
  49.      }
  50. }
  51. </pre><br>
  52. OK<br>
  53. <br>
  54. <p></p>