SAX和DOM的区别是什么?
SAX 使用基于event的处理来阅读XML文档, 它由回调机制实现.当解析器阅读文档的时候,每个解析事件都导致与这个事件相关的特定方法的调用,如认出元素的开始和结束.但是,SAX本身不是XML文档解析器.它是对XML解析器接口的公有域定义,在这里解析器是外部程序.SAX API的公有域部分存在于作为JDK一部分的3个程序包内:
1)org.xml.sax 2)org.xml.sax.helpers 3)org.xml.sax.ext 4)javax.xml.parsers 5)javax.xml.transform
在java术语中包含若干个接口.XMLReader接口定义在org.xml.sax包内.
DOM解析XML文档时,整个文档树都在内存中形成,并作为封装好的Document类型的对象返回个应用程序.它的缺点是占用了大量的内存空间.无论它多大都要全部调入内存空间.但是DOM允许你修改存在的文档或创建新的文档.如果需要利用程序创建XML文档并且将它传送给一个文件或另一个计算机这样的外部目标,DOM就可以大显身手了,而SAX则没有这样的功能.
用Digester解析XML文档
Digester是一个将配置文件转换为java对象的工具,有三个核心概念:
1)元素匹配规则Pattern : 找出xml配置文件中匹配的部分准备处理
2)处理规则Rule: 指定一个处理的规则来处理这些待处理元素
3)对象栈: 按照解析的层次关系,将XML配置文件中解析出的对象依次入栈
Digester解析步骤:
1)创建一个Digester的实例:
2)指定其使用的Pattern和Rule;
3)传递一个引用xml文件的对象参数;
以工作流管理系统为例(blog里有关于工作流管理系统模型):
xml配置文件workflow.xml:
<?xml version="1.0" encoding="gb2312"?>
<workflow name ="hello workflow">
<activities>
<start name="start" id="0001" nextIds="0002,003">
</start>
<task name="task" id="0002" nextIds="0004">
</task>
<task name="task1" id="0003" nextIds="0004">
</task>
<join name="join" id="0004" nextIds="0005">
</join>
<end name="end" id="0005" nextIds="">
</end>
</activities>
</workflow>
指定pattern和rule的xml解析文件rule.xml
<?xml version="1.0"?>
<digester-rules>
<pattern value="workflow">
<object-create-rule
classname="com.itcast.workflow.model.Workflow"/>
<set-properties-rule />
<set-next-rule methodname="setWorkflow" />
<pattern value="activities/start">
<object-create-rule
classname="com.itcast.workflow.model.Start"/>
<set-properties-rule />
<set-next-rule methodname="addActivity" />
</pattern>
<pattern value="activities/task">
<object-create-rule
classname="com.itcast.workflow.model.Task"/>
<set-properties-rule />
<set-next-rule methodname="addActivity" />
</pattern>
<pattern value="activities/join">
<object-create-rule
classname="com.itcast.workflow.model.Join"/>
<set-properties-rule />
<set-next-rule methodname="addActivity" />
</pattern>
<pattern value="activities/end">
<object-create-rule
classname="com.itcast.workflow.model.End"/>
<set-properties-rule />
<set-next-rule methodname="addActivity" />
</pattern>
</pattern>
</digester-rules>
XMLReader.java:
import java.io.IOException;
import java.io.StringReader;
import java.util.List;
import org.apache.commons.digester.Digester;
import org.apache.commons.digester.xmlrules.DigesterLoader;
import org.xml.sax.SAXException;
import com.itcast.workflow.model.Activity;
import com.itcast.workflow.model.Workflow;
public class XmlReader {
public void setWorkflow(Workflow workflow) {
this.workflow = workflow;
}
public XmlReader(String xml) {
this.xml = xml;
}
public void startRead(){
try
{
java.net.URL rulesURL = getClass().getClassLoader().getResource("com/itcast/workflow/xml/rules.xml");
// 创建digester对象并指定解析规则
Digester d = DigesterLoader.createDigester(rulesURL);
//回调机制
d.push(this); //压入栈中
d.parse(new StringReader(xml)); //弹出栈
}
catch(IOException ioe)
{
ioe.printStackTrace();
}
catch(SAXException se)
{
se.printStackTrace();
}
buildRelation();
}
private void buildRelation() {//建立关联
List activities = workflow.getActivities();
for(int i=0;i<activities.size();i++){
Activity activity = (Activity )activities.get(i);
String nextIds = activity.getNextIds();
if(nextIds != null){
String[] ids = nextIds.split(",");
for(int j=0;j<ids.length;j++){
Activity next = getActivityById(ids[j]);
if(next != null){
activity.addNext(next);
}
}
}
}
}
private Activity getActivityById(String id) {
Activity activity = null;
List activities = workflow.getActivities();
for(int i=0;i<activities.size();i++){
Activity a = (Activity )activities.get(i);
if(a.getId().equals(id)){
activity = a;
break;
}
}
return activity;
}
String xml;
Workflow workflow = new Workflow();
public Workflow getWorkflow() {
return workflow;
}
}