1.SAX概念
SXA:Simple API for XML
基于事件驱动(Android中的事件驱动基于回调函数),边加载边解析。
从头到尾逐个读取内容,修改不便,适用于只读的打文档。
用SAX解析XML文档的时候,在读取到文档开始和结束标签时候就会回调一个事件,在读到其他节点与内容的时候也会回调一个事件。
五个主要的回调方法:
startDocument() //处理文档解析开始事件
startElement()
//处理元素开始事件
characters()
//处理元素的字符内容,解析到元素的内容则返回到characters方法中
endElement()
//处理元素结束事件
endDocument()
//处理文档结束事件
2.基本步骤
(1)创建SAXParserFactory对象(newInstance())
(2)根据SAXParserFactory对象的newSAXParser()方法创建SAXParser解析器对象
(3)根据SAXParser解析器对象获得事件源对象XMLReader对象
(4)实例化一个DefaultHandler对象
(5)连接事件源对象到事件处理器DefaultHandler中(setContentHandler方法)
(6)使用XMLReader的parse方法解析从输入源中获取的XML数据
(7)通过DefaultHandler返回需要的数据集合
3.实例
需要解析的xml文档
<?xml version="1.0" encoding="utf-8"?>
<students>
<student id="0">
<name>zhangmq</name>
<gender>female</gender>
<age>24</age>
</student>
<student id="1">
<name>zhouhy</name>
<gender>male</gender>
<age>24</age>
</student>
</students>
根据xml文档定义的Student类
public class Student {
private String id;
private String name;
private String gender;
private String age;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
public String getAge() {
return age;
}
public void setAge(String age) {
this.age = age;
}
public String toString(){
return "Student [id = "+id+" name = "+name +" gender = "+gender+" age = "+age+"]";
}
}
具体解析代码
public class SAXParseHandler extends DefaultHandler {
List<Student> students;
Student student;
String nodeName; //记录当前的元素名字
// 处理文档解析开始事件
@Override
public void startDocument() throws SAXException {
// TODO Auto-generated method stub
Log.d("zhangmq", "startDocument");
students = new ArrayList<Student>();
}
// 处理元素解析开始事件
@Override
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException {
// TODO Auto-generated method stub
Log.d("zhangmq", "startElement");
Log.d("zhangmq", "startElement localName = " + localName);
Log.d("zhangmq", "startElement qName = " + qName);
Log.d("zhangmq",
"startElement attributes.getLength() = "
+ attributes.getLength());
if (localName.equals("student")) {
student = new Student();
for (int i = 0; i < attributes.getLength(); i++) {
if (attributes.getLocalName(i).equals("id")) {
student.setId(attributes.getValue(i));
}
}
} else {
nodeName = localName;
}
}
// 接收字符块通知
@Override
public void characters(char[] ch, int start, int length)
throws SAXException {
// TODO Auto-generated method stub
Log.d("zhangmq", "characters");
Log.d("zhangmq", "characters ch = " + ch);
Log.d("zhangmq", "characters start = " + start);
Log.d("zhangmq", "characters length = " + length);
//这个地方比较容易失误
//若是不加trim,则str可能是一个空字符串,但它不是普通的null或是"",而是" ".
//这样会导致判断str != null && !"".equals(str)的时候失误。千万要注意.
//要判断str是因为还会解析</name>,得到的nodeName跟<name>是一样的.
String str = String.valueOf(ch, start, length).trim();
Log.d("zhangmq", "characters str = " + str);
Log.d("zhangmq", "characters nodeName = " + nodeName);
if (str != null && !"".equals(str)) {
if ("name".equals(nodeName)) {
student.setName(str);
} else if ("gender".equals(nodeName)) {
student.setGender(str);
} else if ("age".equals(nodeName)) {
student.setAge(str);
}
}
}
// 接收元素结束通知
@Override
public void endElement(String uri, String localName, String qName)
throws SAXException {
// TODO Auto-generated method stub
Log.d("zhangmq", "endElement");
// 判断标签是否为student
if (localName.equals("student")) {
students.add(student);
}
}
// 接收文档结束通知
@Override
public void endDocument() throws SAXException {
// TODO Auto-generated method stub
super.endDocument();
Log.d("zhangmq", "endDocument");
}
public String getStudentsString() {
// 再需要+字符串时,str最好定义成"",否则,在显示字符串的时候最前面的是null,例如下面的就是:nullStudent
String str = "";
for (int i = 0; i < students.size(); i++) {
str = str + students.get(i).toString() + "\n";
}
return str;
}
}
解析xml文档
public class SaxParseActivity extends Activity {
private TextView sax_parse_tv;
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_sax);
sax_parse_tv = (TextView) findViewById(R.id.sax_parse);
sax_parse_tv.setText(saxParseXml());
}
private String saxParseXml() {
String str = null;
SAXParserFactory factory = null;
//解析器对象
SAXParser parse = null;
//事件源对象
XMLReader reader = null;
InputStream is = null;
//SAX解析的帮助类,继承DefaultHandler
SAXParseHandler parseHandler = null;
//1.实例化SAXParserFactory对象
factory = SAXParserFactory.newInstance();
try {
//2.使用SAXParserFactory对象实例化SAXParser对象
parse = factory.newSAXParser();
} catch (ParserConfigurationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SAXException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
//3.使用SAXParser对象实例化XMLReader
reader = parse.getXMLReader();
} catch (SAXException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//自己写的SAX解析帮助类,实例化
parseHandler = new SAXParseHandler();
//解析器注册事件
reader.setContentHandler(parseHandler);
try {
//获取xml文件到输入流中
is = getResources().getAssets().open("dom_info.xml");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
InputSource inputSource = new InputSource(is);
try {
//解析文件,事件源
reader.parse(inputSource);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SAXException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
str = parseHandler.getStudentsString();
return str;
}
}