SAX解析:非常类似于流媒体的优点。分析能够立即开始,而不是等待所有的数据被处理。而且,由于应用程序只是在读取数据时检查数据,因此不需要将数据存储在内存中。这对于大型文档来说是个巨大的优点。事实上,应用程序甚至不必解析整个文档;它可以在某个条件得到满足时停止解析。一般来说,
SAX 还比它的替代者 DOM 快许多。
}
}
选择
DOM 还是选择 SAX ?
对于需要自己编写代码来处理
XML 文档的开发人员来说,选择 DOM 还是 SAX 解析模型是一个非常重要的设计决策。
区别:
DOM 采用建立树形结构的方式访问 XML 文档,而 SAX 采用的事件模型。
DOM 解析器把 XML 文档转化为一个包含其内容的树,并可以对树进行遍历。
DOM 解析器把 XML 文档转化为一个包含其内容的树,并可以对树进行遍历。
用 DOM 解析模型的优点是编程容易,开发人员只需要调用建树的指令,然后利用navigation APIs访问所需的树节点来完成任务。可以很容易的添加和修改树中的元素。然而由于使用 DOM 解析器的时候需要处理整个 XML 文档,所以对性能和内存的要求比较高,尤其是遇到很大的 XML 文件的时候。由于它的遍历能力,DOM 解析器常用于 XML 文档需要频繁的改变的服务中。
SAX 解析器采用了基于事件的模型,它在解析 XML 文档的时候可以触发一系列的事件,当发现给定的tag的时候,它可以激活一个回调方法,告诉该方法制定的标签已经找到。SAX 对内存的要求通常会比较低,因为它让开发人员自己来决定所要处理的tag。特别是当开发人员只需要处理文档中所包含的部分数据时,SAX 这种扩展能力得到了更好的体现。
SAX 解析器采用了基于事件的模型,它在解析 XML 文档的时候可以触发一系列的事件,当发现给定的tag的时候,它可以激活一个回调方法,告诉该方法制定的标签已经找到。SAX 对内存的要求通常会比较低,因为它让开发人员自己来决定所要处理的tag。特别是当开发人员只需要处理文档中所包含的部分数据时,SAX 这种扩展能力得到了更好的体现。
但是用 SAX 解析器的时候编码工作会比较困难,而且很难同时访问同一个文档中的多处不同数据。
①
准备活动
1. java.util.Stack<E>是java.util.Vector的子类。<E>
Stack
类表示后进先出(LIFO)的对象堆栈。它通过五个操作对类 Vector 进行了扩展 ,允许将向量视为堆栈。它提供了通常的 push() 和 pop() 操作,以及取栈顶点的 peek() 方法,测试堆栈是否为空的 empty()方法、在堆栈中查找项并确定到栈顶距离的 search 方法。
首次创建堆栈时,它不包含数据项。
2. org.xml.sax.helpers.DefaultHandler
public class DefaultHandler
extends Object
implements EntityResolver, DTDHandler, ContentHandler, ErrorHandler
startElement();接收元素开始的通知。
characters();//接收元素中字符数据的通知。
例如:
创建
H://zmb//Sweet_ForTest_back//source.xml
<?xml version="1.0" encoding="SHIFT_JIS"?>
<elements>
<H-element id="h1">
<moto>_ExtentX</moto>
<pattern>_ExtentX</pattern>
<saki>_cx</saki>
</H-element>
<H-element id="h2">
<moto>_ExtentY</moto>
<pattern>_ExtentY</pattern>
<saki>_cy</saki>
</H-element>
<elements>
<H-element id="h1">
<moto>_ExtentX</moto>
<pattern>_ExtentX</pattern>
<saki>_cx</saki>
</H-element>
<H-element id="h2">
<moto>_ExtentY</moto>
<pattern>_ExtentY</pattern>
<saki>_cy</saki>
</H-element>
<B-element >
<moto>.Col2</moto>
<pattern>//.Col2</pattern>
<saki>.ColSel</saki>
</B-element >
<B-element >
<moto>.MaxRows</moto>
<pattern>//.MaxRows</pattern>
<saki>.Rows</saki>
</B-element >
<moto>.Col2</moto>
<pattern>//.Col2</pattern>
<saki>.ColSel</saki>
</B-element >
<B-element >
<moto>.MaxRows</moto>
<pattern>//.MaxRows</pattern>
<saki>.Rows</saki>
</B-element >
</elements>
解析类:
package doxml;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Stack;
import java.util.HashMap;
import java.util.List;
import java.util.Stack;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.AttributesImpl;
import org.xml.sax.helpers.DefaultHandler;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.AttributesImpl;
import org.xml.sax.helpers.DefaultHandler;
public class SrcXMLParse extends DefaultHandler {
private int iHeader = 0;
private int iBody = 0;
// 接收标签内容,因为characters()方法是以字符流的形式接收内容,
// 如果用string,有可能造成内容缺失
private StringBuffer xmlContent = new StringBuffer();
// 声明一个map对象,并不做初始化
private HashMap<String,String> elementMap = null;
// 定义list对象,存放xml文件内容的列表
private List<HashMap<String,String>> headerElementList = new ArrayList<HashMap<String,String>>();
private List<HashMap<String,String>> bodyElementList = new ArrayList<HashMap<String,String>>();
private Stack<ElementDetails> context = new Stack<ElementDetails>();
/** Default Constructor */
public SrcXMLParse(){
}
/** * Start Document */
public void startDocument() {
}
private int iHeader = 0;
private int iBody = 0;
// 接收标签内容,因为characters()方法是以字符流的形式接收内容,
// 如果用string,有可能造成内容缺失
private StringBuffer xmlContent = new StringBuffer();
// 声明一个map对象,并不做初始化
private HashMap<String,String> elementMap = null;
// 定义list对象,存放xml文件内容的列表
private List<HashMap<String,String>> headerElementList = new ArrayList<HashMap<String,String>>();
private List<HashMap<String,String>> bodyElementList = new ArrayList<HashMap<String,String>>();
private Stack<ElementDetails> context = new Stack<ElementDetails>();
/** Default Constructor */
public SrcXMLParse(){
}
/** * Start Document */
public void startDocument() {
}
/** * End Document */
public void endDocument() {
}
/** Start Element */
public void startElement(String uri, String localName, String qName,
Attributes attribute) throws SAXException {
// 声明一个ElementDetails类的实例,
// 这个类存放的就是标签信息,目的是放到堆栈中
ElementDetails elem = new ElementDetails(uri, localName, qName,
attribute);
// 把信息推入堆栈
context.push(elem);
if (qName.equals("H-element")) {
elementMap = new HashMap<String, String>();
iHeader ++;
}else if(qName.equals("B-element")){
elementMap = new HashMap<String, String>();
iBody ++;
}
// 给stringbuffer清空,以便接收新内容
xmlContent.setLength(0);
}
/** * End Element */
public void endElement(String uri, String localName, String qName)
throws SAXException {
// 如果是</moto>
if (qName.equals("moto")) {
elementMap.put("moto", xmlContent.toString());
// 如果是</pattern>
} else if (qName.equals("pattern")) {
elementMap.put("pattern", xmlContent.toString());
// 如果是</saki>
} else if (qName.equals("saki")) {
elementMap.put("saki", xmlContent.toString());
// 如果是</H-element>
} else if (qName.equals("H-element")) {
// 说明B-element标签结束了,把内容放到列表里(解析的结果---我们的目标)
headerElementList.add(elementMap);
} else if(qName.equals("B-element")){
public void endDocument() {
}
/** Start Element */
public void startElement(String uri, String localName, String qName,
Attributes attribute) throws SAXException {
// 声明一个ElementDetails类的实例,
// 这个类存放的就是标签信息,目的是放到堆栈中
ElementDetails elem = new ElementDetails(uri, localName, qName,
attribute);
// 把信息推入堆栈
context.push(elem);
if (qName.equals("H-element")) {
elementMap = new HashMap<String, String>();
iHeader ++;
}else if(qName.equals("B-element")){
elementMap = new HashMap<String, String>();
iBody ++;
}
// 给stringbuffer清空,以便接收新内容
xmlContent.setLength(0);
}
/** * End Element */
public void endElement(String uri, String localName, String qName)
throws SAXException {
// 如果是</moto>
if (qName.equals("moto")) {
elementMap.put("moto", xmlContent.toString());
// 如果是</pattern>
} else if (qName.equals("pattern")) {
elementMap.put("pattern", xmlContent.toString());
// 如果是</saki>
} else if (qName.equals("saki")) {
elementMap.put("saki", xmlContent.toString());
// 如果是</H-element>
} else if (qName.equals("H-element")) {
// 说明B-element标签结束了,把内容放到列表里(解析的结果---我们的目标)
headerElementList.add(elementMap);
} else if(qName.equals("B-element")){
//(解析的结果---我们的目标)
bodyElementList.add(elementMap);
}
//给stringbuffer清空,以便接收新内容
xmlContent.setLength(0);
//把最后进来的对象弹出堆栈,因为他的标签已经结束,没有再存在的必要了(后进先出)
context.pop();
}
/**
* *Handle the context between the element *@param ch[] *@param start
* *@param length *@return void
*/
public void characters(char ch[], int start, int length)
throws SAXException {
// 把标签内容存到一个stringbuffer对象里,以备处理
xmlContent.append(ch, start, length);
}
/** * Get strA value */
public String getContent() {
return xmlContent.toString();
}
bodyElementList.add(elementMap);
}
//给stringbuffer清空,以便接收新内容
xmlContent.setLength(0);
//把最后进来的对象弹出堆栈,因为他的标签已经结束,没有再存在的必要了(后进先出)
context.pop();
}
/**
* *Handle the context between the element *@param ch[] *@param start
* *@param length *@return void
*/
public void characters(char ch[], int start, int length)
throws SAXException {
// 把标签内容存到一个stringbuffer对象里,以备处理
xmlContent.append(ch, start, length);
}
/** * Get strA value */
public String getContent() {
return xmlContent.toString();
}
/** * Return headerElementList*/
public List<HashMap<String,String>> getHeaderElementList() {
return headerElementList;
}
/** * Return bodyElementList*/
public List<HashMap<String,String>> getBodyElementList() {
return bodyElementList;
}
// 定义一个内部类,接收标签元素信息,供堆栈用
private class ElementDetails {
private String uri;
private String localName;
private String qName;
private Attributes attribute;
public List<HashMap<String,String>> getHeaderElementList() {
return headerElementList;
}
/** * Return bodyElementList*/
public List<HashMap<String,String>> getBodyElementList() {
return bodyElementList;
}
// 定义一个内部类,接收标签元素信息,供堆栈用
private class ElementDetails {
private String uri;
private String localName;
private String qName;
private Attributes attribute;
/*
* Defalut Constructor
*/
public ElementDetails(String uri, String localName, String qName,
Attributes attribute) {
this.uri = uri;
* Defalut Constructor
*/
public ElementDetails(String uri, String localName, String qName,
Attributes attribute) {
this.uri = uri;
this.localName = localName;
this.qName = qName;
// 注意Attributes是一个接口,所以要把他转化为一个AttributesImpl对象
this.attribute = new AttributesImpl(attribute);
}
this.qName = qName;
// 注意Attributes是一个接口,所以要把他转化为一个AttributesImpl对象
this.attribute = new AttributesImpl(attribute);
}
public Attributes getAttribute() {
return attribute;
}
return attribute;
}
public void setAttribute(Attributes attribute) {
this.attribute = new AttributesImpl(attribute);
}
this.attribute = new AttributesImpl(attribute);
}
public String getLocalName() {
return localName;
}
return localName;
}
public void setLocalName(String localName) {
this.localName = localName;
}
this.localName = localName;
}
public String getQName() {
return qName;
}
return qName;
}
public void setQName(String name) {
qName = name;
}
qName = name;
}
public String getUri() {
return uri;
}
return uri;
}
public void setUri(String uri) {
this.uri = uri;
}
}
public static void main(String[] args) {
SrcXMLParse xmlParse = new SrcXMLParse();
SAXParserFactory factory = SAXParserFactory.newInstance();
String absFilePath = "H://zmb//Sweet_ForTest_back//source.xml";
try {
SAXParser parser = factory.newSAXParser();
parser.parse(absFilePath, xmlParse);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
this.uri = uri;
}
}
public static void main(String[] args) {
SrcXMLParse xmlParse = new SrcXMLParse();
SAXParserFactory factory = SAXParserFactory.newInstance();
String absFilePath = "H://zmb//Sweet_ForTest_back//source.xml";
try {
SAXParser parser = factory.newSAXParser();
parser.parse(absFilePath, xmlParse);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
另外startElement方法中的
String attName = attrs.getQName(0);
String attValue = attrs.getValue(0);
也是经常使用到的。
例如
publicvoid startElement(String uri, String localName, String qName,
Attributes attrs) {
tags
.push(qName);
//
把项压入栈顶
// System.out.println(qName);
if
(qName.equals(
"emp"
)) {
String attName = attrs.getQName(0);
String attValue = attrs.getValue(0);
System.
out
.print(
" <"
+ qName +
" "
);
System.
out
.println(attName +
"=/""
+ attValue +
"/">"
);
}