sax解析xml是一个事件驱动的xml解析器结构,当发生了startDocument,startElement事件都会触发响应事件回调函数进行响应。
sax默认的事件响应回调接口是contentHandler,定义了一序列的事件响应接口函数,
- startDocumet/endDocument在文档开始和结束时候回调这个函数,一般用于文档解析的初始化和结尾数据整理。
- startElement/endElement通知一个元素的开始和结束,Attributes在startElement中以参数形式将这个元素的所有属性传递进来。
- Attributes属性定义了getValue(i)/getValue(String qname)/getValue(url, localName);返回第i个或者指定属性名称的属性值;
- getLength()返回属性的个数
- getQName(i) /getLocalName(i)/getURI(I)返回限定名,本地名,名称空间
定义一个javabean用于从xml实例化过来的实例
package com.vincent.org.networkapp.xml;
/**
* xml解析的操作数据实体
*
* @author cindy
*
*/
public class Person {
private Integer id;
private String name;
private Short age;
public Person() {
// TODO Auto-generated constructor stub
}
public Person(Integer id, String name, Short age) {
super();
this.id = id;
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Peron [id=" + id + ", name=" + name + ", age=" + age + "]";
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Short getAge() {
return age;
}
public void setAge(Short age) {
this.age = age;
}
}
定义个handler,就是xml文件的事件处理器
package com.vincent.org.networkapp.xml.saxservice;
import java.util.ArrayList;
import java.util.List;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
import android.util.Log;
import com.vincent.org.networkapp.xml.Person;
/**
* sax是事件驱动式的xml解析器
*
* @author cindy
*
*/
public class SaxHandler extends DefaultHandler {
private static final String TAG = "SAXHandler";
private List<Person> persons;
public List<Person> getPersons() {
return persons;
}
private String perTag;// 记录当前标签的名字
Person person;// 记录当前解析的person
// 开始解析回调
@Override
public void startDocument() throws SAXException {
// TODO Auto-generated method stub
super.startDocument();
persons = new ArrayList<Person>();
Log.i(TAG, "---startDoucument() begin parse---");
}
@Override
public void endDocument() throws SAXException {
// TODO Auto-generated method stub
super.endDocument();
Log.i(TAG, "---endDoucument() stop parse---");
}
@Override
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException {
// TODO Auto-generated method stub
super.startElement(uri, localName, qName, attributes);
if ("person".equals(localName)) {
for (int i = 0; i < attributes.getLength(); i++) {
Log.i(TAG, "attributesName: " + attributes.getLocalName(i)
+ " attributes_value:" + attributes.getValue(i));
person = new Person();
person.setId(Integer.valueOf(attributes.getValue(i)));
}
}
perTag = localName;
Log.i(TAG, qName + "---startElement---");
}
@Override
public void endElement(String uri, String localName, String qName)
throws SAXException {
// TODO Auto-generated method stub
super.endElement(uri, localName, qName);
if ("person".equals(localName)) {
persons.add(person);
person = null;
}// person节点结束
perTag = null;// 一个节点的结束,包括person节点和name节点
Log.i(TAG, qName + "---endElement---");
}
// 遇到文本节点时候回调这个方法
@Override
public void characters(char[] ch, int start, int length)
throws SAXException {
// TODO Auto-generated method stub
super.characters(ch, start, length);
String data = new String(ch, start, length).trim();
if (!"".equals(data.trim())) {
Log.i(TAG, "content: " + data);
if ("name".equals(perTag)) {
person.setName(data);
} else if ("age".equals(perTag)) {
person.setAge(new Short(data));
}
}
}
}
定义一个xml解析的服务类
package com.vincent.org.networkapp.xml.saxservice;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.SAXException;
import android.util.Log;
import com.vincent.org.networkapp.xml.Person;
public class SaxService {
private static final String TAG = "SaxService";
public static List<Person> getPersons(InputStream iStream)
throws ParserConfigurationException, SAXException, IOException {
Log.i(TAG, iStream == null ? "istream是空" : "否");
SAXParserFactory spf = SAXParserFactory.newInstance();
SAXParser saxParser = spf.newSAXParser();
SaxHandler handler = new SaxHandler();
// saxParser.parse(dataXml, handler);
saxParser.parse(iStream, handler);
iStream.close();
return handler.getPersons();
}
}
然后是页面button触发xml解析事件处理函数。
public void saxXml(View view) throws ParserConfigurationException,
SAXException, IOException {
Toast.makeText(this, "saxXml ", Toast.LENGTH_LONG).show();
List<Person> list = parseXml("Person.xml");
// List<Person> list = parseXml();
listView.setAdapter(new ArrayAdapter<Person>(XmlParseActivity.this,
android.R.layout.simple_list_item_1, android.R.id.text1, list));
Log.i(TAG_XmlParseActivity, XmlParseActivity.class.getName());
Log.i(TAG_XmlParseActivity,
XmlParseActivity.class.getResource("Person.xml").toString());
}
/**
* 第一种获取资源的方式,通过getResourceAsStream方式,没有通过android的推荐 获取方式
* xmlpath制定的xml文件必须和我这个函数所在的activity在同一个包下面。
*
* @param XmlPath
* @return
* @throws ParserConfigurationException
* @throws SAXException
* @throws IOException
*/
public List<Person> parseXml(String XmlPath)
throws ParserConfigurationException, SAXException, IOException {
// 第一种获取资源的方式
InputStream iStream = XmlParseActivity.class
.getResourceAsStream(XmlPath);
// Toast.makeText(this, iStream.toString(), Toast.LENGTH_LONG).show();
List<Person> persons = SaxService.getPersons(iStream);
return persons;
}
使用的xml文件
<?xml version="1.0" encoding="utf-8"?>
<!-- 数据操作集 -->
<persons>
<person id="12">
<name>vincent</name>
<age>18</age>
</person>
<person id="15">
<age>19</age>
<name>jack</name>
</person>
<person id="16">
<age>29</age>
<name>kandy</name>
</person>
<person id="17">
<age>23</age>
<name>jim</name>
</person>
<person id="19">
<age>24</age>
<name>tuwen</name>
</person>
</persons>
最后我要提一个问题,就是上面我获取xml文件流是通过java那种原声加载资源的方式,说白了就是根据classpath的路径下寻找。所以上面那个方法限定了xml文件只能放在引用这个xml文件的源码在同一个包下面。
然后我用下面这个获取xml输入流的方式是将xml文件放在res/xml文件夹下面可以用android原生引用xml文件的方式this.getResources()
.openRawResource(R.xml.person)获取到inputstream,但是解析总是报错。 报错 Caused by: org.apache.harmony.xml.ExpatParser$ParseException: At
line 1, column 0: not well-formed (invalid token)
依据这个http://www.xuebuyuan.com/1903031.html更改后还是不行。希望大神可以指点。
private List<Person> parseXml() throws ParserConfigurationException,
SAXException, IOException {
// 第二种获取资源的方式
/**
* 报错 Caused by: org.apache.harmony.xml.ExpatParser$ParseException: At
* line 1, column 0: not well-formed (invalid token)
*/
InputStream iStream = new BufferedInputStream(this.getResources()
.openRawResource(R.xml.person));
// byte[] dataXml = StreamTool.readInputStreamTobyte(iStream);
InputStreamReader isr = new InputStreamReader(iStream, "GB2312");
InputSource inputSource = new InputSource(isr);
// inputSource.setEncoding("GB2312");
Log.i(TAG_XmlParseActivity, iStream == null ? "istream是null"
: "istream不是null");
SAXParserFactory spf = SAXParserFactory.newInstance();
SAXParser saxParser = spf.newSAXParser();
SaxHandler handler = new SaxHandler();
// saxParser.parse(dataXml, handler);
saxParser.parse(inputSource, handler);
// XMLReader xmlReader = saxParser.getXMLReader();
// xmlReader.setContentHandler(handler);
// xmlReader.parse(inputSource);
List<Person> persons = handler.getPersons();
isr.close();
return persons;
}
还是报这个错误。