[b][size=medium]android 2.3 sdk提供的与sax解析相关的类和接口[/size][/b]
它们主要存在与以下的这些包中:
org.xml.sax
org.xml.sax.ext
org.xml.sax.helpers
javax.xml.parsers
android.sax
[b][size=medium]sax相关介绍[/size][/b]
sax存在两个版本1和2,1已经过时了,所以与其相关的api基本也可以忽略(除非是处理遗留代码),现在的话主要使用2.0的sax。
sax是一种推式解析器,所有的事件都是解析器主动发给我们的。它会根据事件的类型,去调用规定好的事件方法。
sax通过以下的接口来规定了一系列的事件方法:
org.xml.sax包中:
ContentHandler,主要包含了在遇到起始标签,结束标签,内容等事件时会调用的方法
ErrorHandler,主要包含了在解析xml时,出现错误时会调用的方法
DTDHandler,主要包含了解析dtd文档时,遇到notation、未解析的entity resolver等事件时,会调用的方法
org.xml.sax.ext包中:
LexicalHandler,主要包含了在遇到comment(注释),dtd declaration(dtd声明),CDATA等事件时会调用的方法
DeclHandler,用在dtd文件中,主要包含了在遇到dtd文档中的相应事件时调用的方法
以下三个很少会用到,这里不做介绍。
Attributes2
EntityResolver2
Locator2
还需要知道的一个类org.xml.sax.helpers.DefaultHandler:
该类可以看作是一个适配器类,就是它实现了ContentHandler, DTDHandler, EntityResover, ErrorHandler,但是在其内部什么也没做,仅仅是为了方便我们使用。
一般的话我们会继承这个类来写事件处理代码,而不是去实现接口。
[b][size=medium]sax解析一般数据[/size][/b]
解析的数据和前一篇中提到的一样:
<root><data><create>8</create><fans>4</fans><home>9</home><mentions>0</mentions><private>0</private></data><errcode>0</errcode><msg>ok</msg><ret>0</ret></root>
它们主要存在与以下的这些包中:
org.xml.sax
org.xml.sax.ext
org.xml.sax.helpers
javax.xml.parsers
android.sax
[b][size=medium]sax相关介绍[/size][/b]
sax存在两个版本1和2,1已经过时了,所以与其相关的api基本也可以忽略(除非是处理遗留代码),现在的话主要使用2.0的sax。
sax是一种推式解析器,所有的事件都是解析器主动发给我们的。它会根据事件的类型,去调用规定好的事件方法。
sax通过以下的接口来规定了一系列的事件方法:
org.xml.sax包中:
ContentHandler,主要包含了在遇到起始标签,结束标签,内容等事件时会调用的方法
ErrorHandler,主要包含了在解析xml时,出现错误时会调用的方法
DTDHandler,主要包含了解析dtd文档时,遇到notation、未解析的entity resolver等事件时,会调用的方法
org.xml.sax.ext包中:
LexicalHandler,主要包含了在遇到comment(注释),dtd declaration(dtd声明),CDATA等事件时会调用的方法
DeclHandler,用在dtd文件中,主要包含了在遇到dtd文档中的相应事件时调用的方法
以下三个很少会用到,这里不做介绍。
Attributes2
EntityResolver2
Locator2
还需要知道的一个类org.xml.sax.helpers.DefaultHandler:
该类可以看作是一个适配器类,就是它实现了ContentHandler, DTDHandler, EntityResover, ErrorHandler,但是在其内部什么也没做,仅仅是为了方便我们使用。
一般的话我们会继承这个类来写事件处理代码,而不是去实现接口。
[b][size=medium]sax解析一般数据[/size][/b]
解析的数据和前一篇中提到的一样:
<root><data><create>8</create><fans>4</fans><home>9</home><mentions>0</mentions><private>0</private></data><errcode>0</errcode><msg>ok</msg><ret>0</ret></root>
<!-- 便于阅读的格式 -->
<root>
<data>
<create>8</create>
<fans>4</fans>
<home>9</home>
<mentions>0</mentions>
<private>0</private>
</data>
<errcode>0</errcode>
<msg>ok</msg>
<ret>0</ret>
</root>
// 解析器创建
SAXParserFactory factory = SAXParserFactory.newInstance();
// 配置要创建的parser的特性,配置特性的方法在android api中是无法调用的(主要是考虑到它是移动设备,某些特性太耗性能了)
// 像腾迅微博返回的xml数据可以交换关闭dtd验证(提升3倍的速度)和命名空间
// factory.setValidating(false); // 在android上默认为false
// factory.setNamespaceAware(false); // 在android上默认为false
// 创建解析器
SAXParser parser = factory.newSAXParser();
InputSource source = new InputSource("d:/test.xml");
MyDefaultHandler handler = new MyDefaultHandler();
parser.parse(source, handler);
// 事件处理类
public class MyDefaultHandler extends DefaultHandler {
@Override
public void startDocument() throws SAXException {
// 文档开始
}
@Override
public void endDocument() throws SAXException {
// 文档结束
}
private static final int root = 0;
private static final int data = 1;
private static final int create = 2;
private static final int fans = 3;
private static final int home = 4;
private static final int mentions = 5;
private static final int privates = 6;
int currentTag = -1;
StringBuilder text = null;
// lName(local name)只有在开启命名空间(setNamespaceAware时才有值),而qName是一直有值的
// 注意在android上,默认命名空间为false,但它的lName总是有值,qName总是没值(如:yd:phone,lName会返回phone)
@Override
public void startElement(String uri, String lName, String qName, Attributes attrs)
throws SAXException {
if ("root".equals(qName)) {
currentTag = root;
} else if ("data".equals(qName)) {
currentTag = data;
} else if ("create".equals(qName)) {
currentTag = create;
text = new StringBuilder();
} else if ("fans".equals(qName)) {
currentTag = fans;
text = new StringBuilder();
} else if ("home".equals(qName)) {
currentTag = home;
text = new StringBuilder();
} else if ("mentions".equals(qName)) {
currentTag = mentions;
text = new StringBuilder();
} else if ("private".equals(qName)) {
currentTag = privates;
text = new StringBuilder();
} else {
// unknow element, just pass
}
}
// lName(local name 没有前缀的名称)只有在开启命名空间(setNamespaceAware时才有值),而qName是一直有值的
// 注意在android上,默认命名空间为false,但它的lName总是有值,qName总是没值(如:yd:phone,lName会返回phone)
@Override
public void endElement(String uri, String lName, String qName)
throws SAXException {
switch (currentTag) {
case root:
// 该元素结束后,马上就是endDocument了。
break;
case data:
currentTag = root;
break;
case create:
// setCreate(text.toString());
currentTag = data;
break;
case fans:
// setFans(text.toString());
currentTag = data;
break;
case home:
// setHome(text.toString());
currentTag = data;
break;
case mentions:
// setMentions(text.toString());
currentTag = data;
break;
case privates:
// setPrivates(text.toString());
currentTag = data;
break;
default:
// unknow element, just pass
}
}
@Override
public void characters(char[] ch, int start, int length)
throws SAXException {
switch (currentTag) {
case create:
case fans:
case home:
case mentions:
case privates:
// get the text
text.append(new String(ch, start, length));
break;
case root:
case data:
default:
// have no interesting text to get
}
}
}