您的位置:首页 > 其它

Digester解析XML的一个列子

2010-09-20 23:17 489 查看
关于Digester的原理这里就不阐述了,感兴趣的可以网上去查找。这里只是记录一个例子。

如果有这样的需求,客户要上传excel文件到Server,Server端需要验证这个excel的格式是否符合指定的格式(表格的column数量以及column name是否符合指定格式)。格式存储在XML文件中,并且以id作为标识,如下。

<?xml version="1.0" encoding="UTF-8"?>
<formats>
<format>
<id>f001</id>
<columns>
<column>编号</column>
<column>姓名</column>
<column>年龄</column>
<column>职位</column>
<column>收入</column>
</columns>
</format>
<format>
<id>f002</id>
<columns>
<column>编号</column>
<column>地址</column>
<column>联系电话</column>
<column>收件人</column>
</columns>
</format>
</formats>


Server端第一步要做的就是加载此XML,将此XML所表达的信息以JAVA对象形式在容器内存中体现出来。注意到第一个ROOT ELEMENT:<formats>,这意味着我们需要这样一个对象来与其对应,创建一个Java对象。

package excel;

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

public class ExcelFormat {
private List<ExcelFormat> formats = new ArrayList<ExcelFormat>();
private List<ColumnVO> columns =new ArrayList<ColumnVO>();
private List<String> columnNames = new ArrayList<String>();
private String id;

public List<String> getColumnNames(){

for(ColumnVO vo : this.columns){
columnNames.add(vo.getColumnName().trim());
}
return columnNames;
}

public ExcelFormat getFormatById(String id){
ExcelFormat format =null;
for(ExcelFormat formatIn :this.formats){
if(id.equalsIgnoreCase(formatIn.getId())){
format =  formatIn;
}
}
return format==null?new ExcelFormat():format ;
}

public List<ExcelFormat> getFormats() {
return formats;
}

public void setFormats(List<ExcelFormat> formats) {
this.formats = formats;
}

public List<ColumnVO> getColumns() {
return columns;
}

public void setColumns(List<ColumnVO> columns) {
this.columns = columns;
}

public String getId() {
return id;
}

public void setId(String id) {
this.id = id;
}

public void addFormat(ExcelFormat format){
this.formats.add(format);
}

public void addColumn(ColumnVO column){
this.columns.add(column);
}
}


ExcelFormat类包含一个List对象,其泛型是类本身,与XML包含多个format元素正好对应了起来。当XML解析完后,ExcelFormat类的实例中只有List元素是含有实际对象引用的(对应多个format元素),而其他成员变量如columns,columnNames,id则都没有实际的对象引用。因为本身ROOT ELEMENT:<formats>,除了含有多个<format>子元素之外,不含有任何其他的子元素了。而这些成员变量在单个format对象(List中的泛型对象)中,都是被赋值的,如id,则对应于format元素的<id>元素,而columns这个List变量,则是当前format元素的中的column子元素的集合。columnNames并没有在解析的时候赋值,而是通过get方法组织数据,返回给调用者。

上面的类是用来承载xml信息的,还需要一个封装Digester解析过程的类。

package excel;

import java.io.IOException;

import org.apache.commons.digester.Digester;
import org.xml.sax.SAXException;

public class ExcelDegister {
private ExcelFormat excelformat;
private String formatXML ;

public ExcelFormat getExcelformat() {
return excelformat;
}

public void setExcelformat(ExcelFormat excelformat) {
this.excelformat = excelformat;
}

public String getFormatXML() {
return formatXML;
}

public void setFormatXML(String formatXML) {
this.formatXML = formatXML;
}

public static void addRule(Digester digester){
digester.addObjectCreate("formats/format", ExcelFormat.class);
digester.addBeanPropertySetter("formats/format/id", "id");
digester.addObjectCreate("formats/format/columns/column", ColumnVO.class);
digester.addBeanPropertySetter("formats/format/columns/column", "columnName");
digester.addSetNext("formats/format/columns/column", "addColumn");
digester.addSetNext("formats/format", "addFormat");
}

public  void parseExcelFormatXML(){
Digester digester = new Digester();
excelformat = new ExcelFormat();
digester.push(excelformat);
addRule(digester);
java.io.File srcfile = new java.io.File("../ExcelParser/src/excel/format.xml");
try {
excelformat =(ExcelFormat)digester.parse(srcfile);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SAXException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("ok");
}

public static void main(String[] args){
new ExcelDegister().parseExcelFormatXML();
}
}


这个类中的parseExcelFormatXML()方法,首先new一个ExcelFormat()对象的实例,将其放入digester实例指定的堆栈中,然后指定Digester解析xml时,需要遵循的规则,其中的addRule(digester)方法。

public static void addRule(Digester digester){
digester.addObjectCreate("formats/format", ExcelFormat.class);
digester.addBeanPropertySetter("formats/format/id", "id");
digester.addObjectCreate("formats/format/columns/column", ColumnVO.class);
digester.addBeanPropertySetter("formats/format/columns/column", "columnName");
digester.addSetNext("formats/format/columns/column", "addColumn");
digester.addSetNext("formats/format", "addFormat");
}


digester.addObjectCreate("formats/format", ExcelFormat.class);


addObjectCreate(String str,Class clazz) 方法,当xml解析器遇到formats/format节点时,进行对象实例的创建,类类型是ExcelFormat类,即创建一个ExcelFormat类的实例。那么如果处理这个对象呢 ?

digester.addSetNext("formats/format", "addFormat");


上面的addSetNext(String nodeFormat,String method)方法指定了处理的方式。注意到开头部分new一个ExcelFormat()对象的实例的时候,当前堆栈中的对象就是这个实例(这个实例对应ROOT ELEMENT节点)。那么就是调用这个实例的"addFormat"方法,来将解析器遇到"formats/format"标签时,创建的excelFormat对象实例,加入到成员变量List中。

与此同时,这个新创建的ExcelFormat实例对象,将会被压入堆栈,而之前的与ROOT ELEMENT对应的ExcelFormat实例对象将会被弹出堆栈。

那么理所当然,应该要做一些事情来丰富这个format实例了。

digester.addBeanPropertySetter("formats/format/id", "id");


这个addBeanPropertySetter(String nodeFormat,String propertyName)方法,看字面意思就是对属性进行赋值,调用其属性的set方法,所以解析器遇到"formats/format/id"这个节点时,就会调用当前excelFormat实例的setId(String id)方法,将id节点对应的值赋值给当前实例。

digester.addObjectCreate("formats/format/columns/column", ColumnVO.class);


这一段代码,顾名思义,解析器遇到"formats/format/columns/column"节点时,创建一个ColumnVO的实例对象。然后调用堆栈中的excelFormat实例的addColumn(Column column)放法,将其存入成员变量的List集合中。当然要配合下面这段代码。

digester.addSetNext("formats/format/columns/column", "addColumn");


以上这些rule,可以不按顺序赋值,digester有其一套调用机制。

对于这个例子,个人认为重点就在于,一定要把握好当前堆栈中的实例对象,然后一步一步向堆栈中压入新的实例对象,进行规则的制定,最后digester按照指定的规则解析xml,给出完整的Java对象,并且与xml结构相对应。实际情况会因为业务逻辑不同,类的设计也不同,但是这个规则制定机制确实百变皆通的。

ColumnVO类,也一并给出,这3个类加一个format.xml可以跑一个main函数。

package excel;

public class ColumnVO {
private String columnName ;
private String culumnValue;

public String getColumnName() {
return columnName;
}
public void setColumnName(String columnName) {
this.columnName = columnName;
}
public String getCulumnValue() {
return culumnValue;
}
public void setCulumnValue(String culumnValue) {
this.culumnValue = culumnValue;
}
}


Good Luck .......
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: