大概思路:
1.首先我们通过输入流来获取要读取的xml文件。
2xml是存放一个对象的数据源,具体对象中的属性我们不知道,那么我们就需要利用反射来读取对象中的属性,利用反射来创建对象,给对象赋值。
3.开始解析,执行开始文档的方法,<> 开始标签里面有值就可以利用attributes.getValue()方法来获取值.
4.读取到属性调用 characters()方法将属性存起来,到结束文档的方法
5结束解析,执行开始文档的方法</>就代表读完一个对象,将对象存入集合
1.提供返回数据源的方法
public ArrayList saxReadXML(InputStream is,Class aClass) throws Exception {
this.aClass=aClass;
SAXParserFactory factory = SAXParserFactory.newInstance();//获得解析工厂
SAXParser parser = factory.newSAXParser();//获得解析器
parser.parse(is,new SaxHepler());//加载要解析的数据
return list;
}
2.封装DefaultHandler解析类
class SaxHepler extends DefaultHandler{
@Override
public void startDocument() throws SAXException {
super.startDocument();//文档开始
}
@Override
public void endDocument() throws SAXException {
super.endDocument();//文档结束
}
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
super.startElement(uri, localName, qName, attributes);
/**
* 获得这个类的名字转小写
* 1.例:<sudent> 的这个对象是Student ,转成student
*/
String name = aClass.getSimpleName().toLowerCase();
if(qName.equals(name)){
try {
object= aClass.newInstance();//创建这个class对象
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
}
Field[] declaredFields = aClass.getDeclaredFields();//获得这个class对象的字段
for (int i=0;i<declaredFields.length;i++){
//attributes 这个参数就是开始标签里的属性 例:<Student id="1" name="张三">
for(int j=0;j<attributes.getLength();j++){
String name1 = declaredFields[i].getName();//获取这个标签名
String qName1 = attributes.getQName(j);//获取标签里的值
if(name1.equals(qName1)){
try {
declaredFields[i].set(object,attributes.getValue(j));//给这个对象设置值
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
}
}
}
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
super.endElement(uri, localName, qName);
String name = aClass.getSimpleName().toLowerCase();//同上
Field[] declaredFields = aClass.getDeclaredFields();//获取这个对象里的属性
if(qName.equals(name)){//如果判断结束了</student> 那么就将这个对象存入集合
list.add(object);
}
for (int i=0;i<declaredFields.length;i++){//通过属性字段来遍历每一个属性
String name1 = declaredFields[i].getName();//获得每个字段的属性名字
if(qName.equals(name1)){
try {
declaredFields[i].set(object,string);//设置值
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
}
@Override
public void characters(char[] ch, int start, int length) throws SAXException {
super.characters(ch, start, length);
string=new String(ch,start,length);//存起来
}
}
3.使用的写法
River student=null;
try {
InputStream open = getAssets().open("rivers.xml");
ArrayList<River> arrayList = new SaxTool().saxReadXML(open, River.class);
for(int i=0;i<arrayList.size();i++){
student= arrayList.get(i);
textView.append(student.toString()+"\n");
}
} catch (Exception e) {
e.printStackTrace();
}
4.解析的XML文件
<?xml version="1.0" encoding="utf-8"?>
<rivers>
<river name="灵渠" length="605">
<introduction>
灵渠在广西壮族自治区兴安县境内,是世界上最古老的运河之一,有着“世界古代水利建筑明珠”的美誉。灵渠古称秦凿渠、零渠、陡河、兴安运河,于公元前214年凿成通航,距今已2217年,仍然发挥着功用。
</introduction>
<imageurl>
http://imgsrc.baidu.com/baike/pic/item/389aa8fdb7b8322e08244d3c.jpg
</imageurl>
</river>
<river name="胶莱运河" length="200">
<introduction>
胶莱运河南起黄海灵山海口,北抵渤海三山岛,流经现胶南、胶州、平度、高密、昌邑和莱州等,全长200公里,流域面积达5400平方公里,南北贯穿山东半岛,沟通黄渤两海。胶莱运河自平度姚家村东的分水岭南北分流。南流由麻湾口入胶州湾,为南胶莱河,长30公里。北流由海仓口入莱州湾,为北胶莱河,长100余公里。
</introduction>
<imageurl>
http://imgsrc.baidu.com/baike/pic/item/389aa8fdb7b8322e08244d3c.jpg
</imageurl>
</river>
<river name="苏北灌溉总渠" length="168">
<introduction>
位于淮河下游江苏省北部,西起洪泽湖边的高良涧,流经洪泽,青浦、淮安,阜宁、射阳,滨海等六县(区),东至扁担港口入海的大型人工河道。全长168km。
</introduction>
<imageurl>
http://imgsrc.baidu.com/baike/pic/item/389aa8fdb7b8322e08244d3c.jpg
</imageurl>
</river>
</rivers>