JAVA SAX之我的Digester

JAVA SAX之我的Digester

Apache Common Digester是一个很优秀的XML解析工具,居于SAX技术,下面是我一个简单实现( 点击下载源代码):
1、类图:

2、规则定义:
2-1、MyRule抽象类:
package  mydigest;

import  org.xml.sax.Attributes;

/** */ /**
 * 规则抽象类
 * 
@author kinkding
 
*/

public   abstract   class  MyRule  {
    
protected MyDigester dig = null;
    
protected String namespaceURI = null;

    
public void setDigester(MyDigester dig) {
        
this.dig = dig;
    }


    
public void setNamespaceURI(String namespaceURI) {
        
this.namespaceURI = namespaceURI;
    }


    
public String getNamespaceURI() {
        
return this.namespaceURI;
    }


    
/** *//** 规则使用完成 */
    
public void finish() throws Exception {

    }


    
/** *//** 开始处理 */
    
public void begin(String namespace, String name, Attributes attributes) throws Exception {

    }


    
/** *//** 处理中 */
    
public void body(String namespace, String name, String text) throws Exception {

    }


    
/** *//** 处理结束 */
    
public void end(String namespace, String name) throws Exception {

    }


}


2-2、创建对象规则:
package  mydigest;

import  org.xml.sax.Attributes;

/** */ /** 创建对象 */
public   class  MyObjCreateRule  extends  MyRule  {
    
protected String className = null;

    
public MyObjCreateRule(Class<?> clazz) {
        
this.className = clazz.getName();
    }


    
public void begin(String namespace, String name, Attributes attributes) throws Exception {
        String realClassName 
= className;
        
if (name != null{
            
// 形如:person="com.info.Person"
            String value = attributes.getValue(name);
            
if (value != null{
                realClassName 
= value;
            }

        }

        
        
// 创建实例并放置到堆栈中
        Class<?> clazz = dig.getClassLoader().loadClass(realClassName);
        Object instance 
= clazz.newInstance();
        dig.push(instance);
    }


    
public void end(String namespace, String name) throws Exception {
        
// 从堆栈中弹出对象
        dig.pop();
    }

}


2-3、设置属性规则:
package  mydigest;

import  java.util.HashMap;

import  org.apache.commons.beanutils.BeanUtils;
import  org.xml.sax.Attributes;

public   class  MySetPropRule  extends  MyRule  {
    
public void begin(String namespace, String name, Attributes attributes) throws Exception {
        HashMap
<String, String> values = new HashMap<String, String>();
        
// 获取属性及值
        for (int i = 0; i < attributes.getLength(); i++{
            String temp 
= attributes.getLocalName(i);
            
if ("".equals(temp)) {
                temp 
= attributes.getQName(i);
            }

            String value 
= attributes.getValue(i);
            
if (temp != null{
                values.put(temp, value);
            }

        }


        Object top 
= dig.peek();
        BeanUtils.populate(top, values);
    }

}


2-4、MySetNextRule:
package  mydigest;

import  org.apache.commons.beanutils.MethodUtils;

public   class  MySetNextRule  extends  MyRule  {
    
protected String methodName = null;

    
public MySetNextRule(String methodName) {
        
this.methodName = methodName;
    }


    
public void end(String namespace, String name) throws Exception {
        Object child 
= dig.peek(0);
        Object parent 
= dig.peek(1);

        Class
<?> paramTypes[] = new Class<?>[1];
        paramTypes[
0= child.getClass();
        MethodUtils.invokeMethod(parent, methodName, 
new Object[] { child }, paramTypes);
    }

}


2-5、方法调用规则:
package  mydigest;

import  org.apache.commons.beanutils.ConvertUtils;
import  org.apache.commons.beanutils.MethodUtils;
import  org.xml.sax.Attributes;

public   class  MyCallMethodRule  extends  MyRule  {
    
protected int targetOffset = 0;
    
protected String methodName = null;
    
protected int paramCount = 0;
    
protected Class<?> paramTypes[] = null;
    
protected String bodyText = null;

    
public MyCallMethodRule(int targetOffset, String methodName, int paramCount) {
        
this.targetOffset = targetOffset;
        
this.methodName = methodName;
        
this.paramCount = paramCount;
        
// 参数类型初始化
        if (paramCount == 0{
            
this.paramTypes = new Class[] { String.class };
        }
 else {
            
this.paramTypes = new Class[paramCount];
            
for (int i = 0; i < this.paramTypes.length; i++{
                
this.paramTypes[i] = String.class;
            }

        }

    }


    
public void begin(String namespace, String name, Attributes attributes) throws Exception {
        
if (paramCount > 0{
            Object parameters[] 
= new Object[paramCount];
            
for (int i = 0; i < parameters.length; i++{
                parameters[i] 
= null;
            }

            
// 参数入栈
            dig.pushParams(parameters);
        }


    }


    
public void body(String namespace, String name, String text) throws Exception {
        
// 只针对0个参数的情况提取元素中间值
        if (paramCount == 0{
            
this.bodyText = text.trim();
        }

    }


    
public void end(String namespace, String name) throws Exception {
        Object parameters[] 
= null;
        
if (paramCount > 0{
            parameters 
= (Object[]) dig.popParams();
            
if (paramCount == 1 && parameters[0== null{
                
return;
            }

        }
 else if (paramTypes != null && paramTypes.length != 0{
            
if (bodyText == null{
                
return;
            }

            parameters 
= new Object[1];
            parameters[
0= bodyText;
            
if (paramTypes.length == 0{
                paramTypes 
= new Class[1];
                paramTypes[
0= String.class;
            }

        }


        Object paramValues[] 
= new Object[paramTypes.length];
        
for (int i = 0; i < paramTypes.length; i++{
            
// 确定是否需要转换
            if (parameters[i] == null
                    
|| (parameters[i] instanceof String && !String.class.isAssignableFrom(paramTypes[i]))) {

                paramValues[i] 
= ConvertUtils.convert((String) parameters[i], paramTypes[i]);
            }
 else {
                paramValues[i] 
= parameters[i];
            }

        }


        Object target;
        
if (targetOffset >= 0{
            target 
= dig.peek(targetOffset);
        }
 else {
            target 
= dig.peek(dig.getCount() + targetOffset);
        }

        
if (target == null{
            StringBuffer sb 
= new StringBuffer();
            sb.append(
"[CallMethodRule]{");
            sb.append(dig.match);
            sb.append(
"} Call target is null (");
            sb.append(
"targetOffset=");
            sb.append(targetOffset);
            sb.append(
",stackdepth=");
            sb.append(dig.getCount());
            sb.append(
")");
            
throw new org.xml.sax.SAXException(sb.toString());
        }

        MethodUtils.invokeMethod(target, methodName, paramValues, paramTypes);
    }

}


2-6、参数调用规则:
package  mydigest;

import  java.util.Stack;

import  org.xml.sax.Attributes;

public   class  MyCallParamRule  extends  MyRule  {
    
protected String attributeName = null;
    
protected int paramIndex = 0;
    
protected Stack<String> bodyTextStack;

    
public MyCallParamRule(int paramIndex, String attributeName) {
        
this.paramIndex = paramIndex;
        
this.attributeName = attributeName;
    }


    
public void begin(String namespace, String name, Attributes attributes) throws Exception {
        Object param 
= null;
        
if (attributeName != null{
            param 
= attributes.getValue(attributeName);
        }


        
if (param != null{
            
// 给参数赋值
            Object parameters[] = (Object[]) dig.peekParams();
            parameters[paramIndex] 
= param;
        }

    }


    
public void body(String namespace, String name, String text) throws Exception {
         
if (attributeName == null{
                
if (bodyTextStack == null{
                    bodyTextStack 
= new Stack<String>();
                }

                bodyTextStack.push(text.trim());
            }

    }


    
public void end(String namespace, String name) throws Exception {
        
if (bodyTextStack != null && !bodyTextStack.empty()) {
            Object parameters[] 
= (Object[]) dig.peekParams();
            parameters[paramIndex] 
= bodyTextStack.pop();
        }

    }


}


2-7、嵌套属性设置:
package  mydigest;

import  java.beans.PropertyDescriptor;
import  java.util.ArrayList;
import  java.util.LinkedList;
import  java.util.List;

import  org.apache.commons.beanutils.BeanUtils;
import  org.apache.commons.beanutils.PropertyUtils;
import  org.xml.sax.Attributes;

public   class  MySetNestedPropRule  extends  MyRule  {

    
public void begin(String namespace, String name, Attributes attributes) throws Exception {
        AnyChildRule anyChildRule 
= new AnyChildRule();
        anyChildRule.setDigester(dig);
        AnyChildRules newRules 
= new AnyChildRules(anyChildRule);
        newRules.init(dig.getMatch() 
+ "/", dig.getRules());
        dig.setRules(newRules);
    }


    
private class AnyChildRules implements MyRules {
        
private MyRules decoratedRules = null;
        
private String matchPrefix = null;
        
private ArrayList<MyRule> rules = new ArrayList<MyRule>(1);
        
private AnyChildRule rule;

        
public AnyChildRules(AnyChildRule rule) {
            
this.rule = rule;
            rules.add(rule);
        }


        
public void add(String pattern, MyRule rule) {

        }


        
public List<MyRule> match(String namespaceURI, String pattern) {
            List
<MyRule> match = decoratedRules.match(namespaceURI, pattern);
            
if ((pattern.startsWith(matchPrefix)) && (pattern.indexOf('/', matchPrefix.length()) == -1)) {
                
if ((match == null || match.size() == 0)) {
                    
return rules;
                }
 else {
                    LinkedList
<MyRule> newMatch = new LinkedList<MyRule>(match);
                    newMatch.addLast(rule);
                    
return newMatch;
                }

            }
 else {
                
return match;
            }

        }


        
public List<MyRule> rules() {
            
return decoratedRules.rules();
        }


        
public void setDigester(MyDigester dig) {
        }


        
public void init(String prefix, MyRules rules) {
            matchPrefix 
= prefix;
            decoratedRules 
= rules;
        }


        
public MyRules getOldRules() {
            
return decoratedRules;
        }


    }


    
private class AnyChildRule extends MyRule {
        
private String currChildElementName = null;

        
public void begin(String namespace, String name, Attributes attributes) throws Exception {
            currChildElementName 
= name;
        }


        
public void body(String namespace, String name, String text) throws Exception {
            String propName 
= currChildElementName;
            Object top 
= dig.peek();
            text 
= text.trim();

            
// 验证是否存在相应属性
            PropertyDescriptor desc = PropertyUtils.getPropertyDescriptor(top, propName);
            
if (desc == null{
                
throw new NoSuchMethodException("Bean has no property named " + propName);
            }

            
try {
                BeanUtils.setProperty(top, propName, text);
            }
 catch (NullPointerException e) {
                
throw e;
            }

        }


        
public void end(String namespace, String name) throws Exception {
            currChildElementName 
= null;
        }

    }

}


3、MyRules及其实现类:
3-1、接口:

package  mydigest;

import  java.util.List;

public   interface  MyRules  {
    
public void setDigester(MyDigester dig);

    
public void add(String pattern, MyRule rule);

    
public List<MyRule> rules();

    
public List<MyRule> match(String namespaceURI, String pattern);
}

3-2、实现类:
package  mydigest;

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

public   class  MyRulesBase  implements  MyRules  {
    
protected MyDigester digester = null;
    
// 缓存:同一个pattern会对应多个规则
    protected HashMap<String, List<MyRule>> cache = new HashMap<String, List<MyRule>>();
    
protected String namespaceURI = null;
    
// 所有规则列表
    protected ArrayList<MyRule> rules = new ArrayList<MyRule>();

    
public void setDigester(MyDigester dig) {
        
this.digester = dig;
    }


    
public void add(String pattern, MyRule rule) {
        
int patternLength = pattern.length();
        
// 去掉最后一个斜线
        if (patternLength > 1 && pattern.endsWith("/")) {
            pattern 
= pattern.substring(0, patternLength - 1);
        }


        List
<MyRule> list = cache.get(pattern);
        
if (list == null{
            list 
= new ArrayList<MyRule>();
            cache.put(pattern, list);
        }

        list.add(rule);
        rules.add(rule);
        
if (this.digester != null{
            rule.setDigester(
this.digester);
        }

        
if (this.namespaceURI != null{
            rule.setNamespaceURI(
this.namespaceURI);
        }

    }


    
public List<MyRule> rules() {
        
return this.rules;
    }


    
public List<MyRule> match(String namespaceURI, String pattern) {
        List
<MyRule> rulesList = lookup(namespaceURI, pattern);
        
if ((rulesList == null|| (rulesList.size() < 1)) {
            String longKey 
= "";
            
for (String key : cache.keySet()) {
                
if (key.startsWith("*/")) {
                    
// pattern -> key:
                    
// (1):foo -> */foo 
                    
// (2):foo/bar->*/bar
                    if (pattern.equals(key.substring(2)) || pattern.endsWith(key.substring(1))) {
                        
// 查找最匹配的
                        if (key.length() > longKey.length()) {
                            rulesList 
= lookup(namespaceURI, key);
                            longKey 
= key;
                        }

                    }

                }

            }

        }

        
if (rulesList == null{
            rulesList 
= new ArrayList<MyRule>();
        }

        
return (rulesList);
    }


    
/** *//** 根据patter查找匹配的规则列表 */
    
protected List<MyRule> lookup(String namespaceURI, String pattern) {
        List
<MyRule> list = this.cache.get(pattern);
        
if (list == null{
            
return (null);
        }

        
if ((namespaceURI == null|| (namespaceURI.length() == 0)) {
            
return (list);
        }


        ArrayList
<MyRule> results = new ArrayList<MyRule>();
        
for (MyRule item : list) {
            
if ((namespaceURI.equals(item.getNamespaceURI())) || (item.getNamespaceURI() == null)) {
                results.add(item);
            }

        }

        
return (results);

    }


}


4、Digester类:
package  mydigest;

import  java.io.File;
import  java.io.FileInputStream;
import  java.util.List;
import  java.util.Stack;

import  javax.xml.parsers.SAXParser;
import  javax.xml.parsers.SAXParserFactory;

import  org.xml.sax.Attributes;
import  org.xml.sax.InputSource;
import  org.xml.sax.SAXException;
import  org.xml.sax.XMLReader;
import  org.xml.sax.helpers.DefaultHandler;

public   class  MyDigester  extends  DefaultHandler  {
    
// 堆栈
    protected Stack<Object> stack = new Stack<Object>();
    
// 根对象
    protected Object root = null;
    
// 
    protected MyRules rules = null;
    
protected XMLReader reader = null;
    
protected SAXParser parser = null;
    
protected Stack<StringBuffer> bodyTexts = new Stack<StringBuffer>();
    
protected StringBuffer bodyText = new StringBuffer();
    
protected String match = "";
    
protected Stack<List<MyRule>> matches = new Stack<List<MyRule>>();
    
protected ClassLoader classLoader = null;
    
protected Stack<Object> params = new Stack<Object>();

    
public void push(Object object) {
        
if (stack.size() == 0{
            root 
= object;
        }

        stack.push(object);
    }


    
public void addRule(String pattern, MyRule rule) {
        rule.setDigester(
this);
        getRules().add(pattern, rule);
    }


    
public MyRules getRules() {
        
if (this.rules == null{
            
this.rules = new MyRulesBase();
            
this.rules.setDigester(this);
        }

        
return this.rules;

    }


    
public void addObjectCreate(String pattern, Class<?> clazz) {
        addRule(pattern, 
new MyObjCreateRule(clazz));
    }


    
public void addSetProperties(String pattern) {
        addRule(pattern, 
new MySetPropRule());
    }


    
public void addSetNext(String pattern, String methodName) {
        addRule(pattern, 
new MySetNextRule(methodName));
    }


    
public void addCallMethod(String pattern, String methodName, int paramCount) {
        addRule(pattern, 
new MyCallMethodRule(0, methodName, paramCount));
    }


    
public void addCallParam(String pattern, int paramIndex, String attributeName) {
        addRule(pattern, 
new MyCallParamRule(paramIndex, attributeName));
    }


    
public void addCallParam(String pattern, int paramIndex) {
        addRule(pattern, 
new MyCallParamRule(paramIndex, null));
    }


    
public void addSetNestedProperties(String pattern) {
        addRule(pattern, 
new MySetNestedPropRule());
    }


    
public Object parse(File file) throws Exception {
        InputSource input 
= new InputSource(new FileInputStream(file));
        input.setSystemId(file.toURI().toURL().toString());
        getXMLReader().parse(input);
        
return root;
    }


    
public XMLReader getXMLReader() throws Exception {
        
if (reader == null{
            reader 
= getParser().getXMLReader();
        }

        reader.setDTDHandler(
this);
        reader.setContentHandler(
this);
        reader.setEntityResolver(
this);
        reader.setErrorHandler(
this);
        
return reader;
    }


    
public SAXParser getParser() throws Exception {
        
if (parser != null{
            
return (parser);
        }

        parser 
= SAXParserFactory.newInstance().newSAXParser();
        
return parser;
    }


    
public void startDocument() throws SAXException {
    }


    
public void endDocument() throws SAXException {
        
for (MyRule r : this.getRules().rules()) {
            
try {
                r.finish();
            }
 catch (Exception e) {
                e.printStackTrace();
            }

        }

        stack.clear();
    }


    
public void startElement(String namespaceURI, String localName, String fullName, Attributes attributes)
            
throws SAXException {
        bodyTexts.push(bodyText);
        bodyText 
= new StringBuffer();
        String name 
= localName;
        
if ((name == null|| (name.length() < 1)) {
            name 
= fullName;
        }

        StringBuffer sb 
= new StringBuffer(match);
        
if (match.length() > 0{
            sb.append(
'/');
        }

        sb.append(name);
        
// 得到新的匹配字符
        match = sb.toString();
        List
<MyRule> rules = getRules().match(namespaceURI, match);
        matches.push(rules);
        
if ((rules != null&& (rules.size() > 0)) {
            
for (int i = 0; i < rules.size(); i++{
                
try {
                    MyRule rule 
= rules.get(i);
                    rule.begin(namespaceURI, name, attributes);
                }
 catch (Exception e) {
                    e.printStackTrace();
                    
throw new SAXException(e);
                }

            }

        }

    }


    
public void characters(char buffer[], int start, int length) throws SAXException {
        bodyText.append(buffer, start, length);
    }


    
public void endElement(String namespaceURI, String localName, String fullName) throws SAXException {
        String name 
= localName;
        
if ((name == null|| (name.length() < 1)) {
            name 
= fullName;
        }

        List
<MyRule> rules = matches.pop();
        
if ((rules != null&& (rules.size() > 0)) {
            String bodyText 
= this.bodyText.toString();
            
for (int i = 0; i < rules.size(); i++{
                
try {
                    MyRule rule 
= rules.get(i);
                    rule.body(namespaceURI, name, bodyText);
                }
 catch (Exception e) {
                    e.printStackTrace();
                    
throw new SAXException(e);
                }

            }

        }

        
// bodyText 退栈
        bodyText = bodyTexts.pop();
        
if (rules != null{
            
// 顺序是从后到前
            for(int i=rules.size()-1;i>=0;i--){
                
try {
                    MyRule rule 
= rules.get(i);
                    rule.end(namespaceURI, name);
                }
 catch (Exception e) {
                    e.printStackTrace();
                    
throw new SAXException(e);
                }

            }

        }


        
// 将匹配字符向前回缩一个单元
        int slash = match.lastIndexOf('/');
        
if (slash >= 0{
            match 
= match.substring(0, slash);
        }
 else {
            match 
= "";
        }

    }


    
public ClassLoader getClassLoader() {
        
if (this.classLoader != null{
            
return (this.classLoader);
        }

        ClassLoader classLoader 
= Thread.currentThread().getContextClassLoader();
        
if (classLoader != null{
            
return (classLoader);
        }

        
return (this.getClass().getClassLoader());
    }


    
public Object peek() {
        
// 取得最后入栈的对象
        return this.stack.peek();
    }


    
// 0:最后一个入栈的对象
    public Object peek(int n) {
        
int index = (stack.size() - 1- n;
        
if (index < 0{
            
return (null);
        }

        
// 第一个入栈的index为0,之后递增
        return (stack.get(index));
    }


    
public Object pop() {
        
return this.stack.pop();
    }


    
public int getCount() {
        
return (stack.size());
    }


    
public void pushParams(Object object) {
        
this.params.push(object);
    }


    
public Object popParams() {
        
return this.params.pop();
    }


    
public Object peekParams() {
        
return this.params.peek();
    }


    
public String getMatch() {
        
return match;
    }


    
public void setRules(MyRules rules) {
        
this.rules = rules;
        
this.rules.setDigester(this);
    }


}

5、测试:
5-1、业务类:
public   class  AddressBook {
    LinkedList people 
=   new  LinkedList();
    
    
public   void  addPerson(Person p) {
        people.addLast(p);
    }
    
    
public   void  print() {
        System.out.println(
" Address book has  "   +  people.size()  +   "  entries " );
        
for (Iterator i  =  people.iterator(); i.hasNext(); ) {
            Person p 
=  (Person) i.next();
            p.print();
        }
    }
}

public   class  Person {
  
private   int  id;
  
private  String category;
  
private  String name;
  
private  HashMap emails  =   new  HashMap();
  
private  List addresses  =   new  ArrayList();
  
  
/**  
   * A unique id for this person. Note that the Digester automatically
   * converts the id to an integer.
   
*/
  
public   void  setId( int  id) {
      
this .id  =  id;
  }
  
  
public   void  setCategory(String category) {
      
this .category  =  category;
  }
  
  
public   void  setName(String name) {
      
this .name  =  name;
  }
  
  
/**  we assume only one email of each type  */
  
public   void  addEmail(String type, String address) {
      emails.put(type, address);
  }
  
  
public   void  addAddress( Address addr ) {
     addresses.add( addr );
  }

  
public   void  print() {
      System.out.println(
" Person # "   +  id);
      System.out.println(
"   category= "   +  category);
      System.out.println(
"   name= "   +  name);
      
      
for (Iterator i  =  emails.keySet().iterator(); i.hasNext(); ) {
          String type 
=  (String) i.next();
          String address 
=  (String) emails.get(type);
          
          System.out.println(
"   email (type  "   +  type  +   " ) :  "   +  address);
      }
      
      
for (Iterator i  =  addresses.iterator(); i.hasNext(); ) {
          Address addr 
=  (Address) i.next();
          addr.print(System.out, 
2 );
      }
  }
}

public   class  Address {
    
private  String type;
    
private  String street;
    
private  String city;
    
private  String state;
    
private  String zip;
    
private  String country;

    
public  String toString() {
        StringBuffer sb 
=   new  StringBuffer();
        sb.append(
"  address (type  "   +  type  +   " )\n " );
        sb.append(
"         "   +  street  +   " \n " );
        sb.append(
"         "   +  city  +   "   "   +  state  +   "   "   +  zip  +   " \n " );
        sb.append(
"         "   +  country  +   " \n " );
        
return  sb.toString();
    }

    
public   void  print(java.io.PrintStream out,  int  indentAmount) {
        StringBuffer indentStr 
=   new  StringBuffer(indentAmount);
        
for  (; indentAmount  >   0 -- indentAmount) {
            indentStr.append(
'   ' );
        }

        out.print(indentStr);
        out.print(
" address type:  " );
        out.println(type);

        out.print(indentStr);
        out.println(
"    "   +  street);

        out.print(indentStr);
        out.println(
"    "   +  city  +   "   "   +  state  +   "   "   +  zip);

        out.print(indentStr);
        out.println(
"    "   +  country);
    }

    
public  String getStreet() {
        
return  street;
    }

    
public   void  setStreet(String street) {
        
this .street  =  street;
    }

    
public  String getCity() {
        
return  city;
    }

    
public   void  setCity(String city) {
        
this .city  =  city;
    }

    
public  String getState() {
        
return  state;
    }

    
public   void  setState(String state) {
        
this .state  =  state;
    }

    
public  String getZip() {
        
return  zip;
    }

    
public   void  setZip(String zip) {
        
this .zip  =  zip;
    }

    
public  String getCountry() {
        
return  country;
    }

    
public   void  setCountry(String country) {
        
this .country  =  country;
    }

    
public  String getType() {
        
return  type;
    }

    
public   void  setType(String type) {
        
this .type  =  type;
    }
}

5-2、XML文件:
<? xml version='1.0' ?>
< address-book >
  
< person  id ="1"  category ="acquaintance" >
    
< name > Gonzo </ name >
    
< email  type ="business" > [email protected] </ email >
    
< address >
      
< type > home </ type >
      
< street > 123 Maine Ave. </ street >
      
< city > Las Vegas </ city >
      
< state > NV </ state >
      
< zip > 01234 </ zip >
      
< country > USA </ country >
    
</ address >
    
< address >
      
< type > business </ type >
      
< street > 234 Maple Dr. </ street >
      
< city > Los Angeles </ city >
      
< state > CA </ state >
      
< zip > 98765 </ zip >
      
< country > USA </ country >
    
</ address >
  
</ person >

  
< person  id ="2"  category ="rolemodel" >
    
< name > Kermit </ name >
    
< email  type ="business" > [email protected] </ email >
    
< email  type ="home" > [email protected] </ email >
    
< address >
      
< type > business </ type >
      
< street > 987 Brown Rd </ street >
      
< city > Las Cruces </ city >
      
< state > NM </ state >
      
< zip > 75321 </ zip >
      
< country > USA </ country >
    
</ address >
  
</ person >

</ address-book >

5-3、测试类:
public   class  MyDigestTest {
    
public   static   void  main(String[] args) {
        String file 
=   " example.xml " ;
        MyDigester dig 
=   new  MyDigester();
        AddressBook book 
=   new  AddressBook();
        dig.push(book);

        
//  添加生成规则(有先后顺序):
        
//  创建对象
        dig.addObjectCreate( " address-book/person " , Person. class );
        
//  设置属性
        dig.addSetProperties( " address-book/person " );
        dig.addSetNext(
" address-book/person " " addPerson " );
        
//  一个参数的情况
        dig.addCallMethod( " address-book/person/name " " setName " 0 );
        
//  两个参数的情况
        dig.addCallMethod( " address-book/person/email " " addEmail " 2 );
        dig.addCallParam(
" address-book/person/email " 0 " type " );
        dig.addCallParam(
" address-book/person/email " 1 );
        dig.addObjectCreate(
" address-book/person/address " , Address. class );
        dig.addSetNext(
" address-book/person/address " " addAddress " );
        dig.addSetNestedProperties(
" address-book/person/address " );

        java.io.File srcfile 
=   new  java.io.File(file);
        
try  {
            dig.parse(srcfile);
        } 
catch  (Exception e) {
            
//  TODO Auto-generated catch block
            e.printStackTrace();
        }
        book.print();
    }
}

5-4、输出结果:
Address book has  2  entries
Person #
1
  category
= acquaintance
  name
= Gonzo
  email (type business) : [email protected]
  address type: home
    
123  Maine Ave.
    Las Vegas NV 
01234
    USA
  address type: business
    
234  Maple Dr.
    Los Angeles CA 
98765
    USA
Person #
2
  category
= rolemodel
  name
= Kermit
  email (type business) : [email protected]
  email (type home) : [email protected]
  address type: business
    
987  Brown Rd
    Las Cruces NM 
75321
    USA

你可能感兴趣的:(JAVA SAX之我的Digester)