Android中操作XML——Sax篇
分类:Android
阅读 (1,872)
Add comments
12月 272012
Sax其实只是一个封装了对XML支持的字符串解析器,sax不像DOM方法要把文件全部加载到内存后再进行解析,而是一边读取文件内容一边对已读取的内容进行解析,它提供的一些方法比如startDocument, startElement等都是在读取到相关的内容后抛出的事件,以便我们可以在此时将数据存到自己的数据结构中。
因为解析XML的时候,要在一个继承自DefaultHandler的类中进行,所以最好对要解析的XML数据定义一个类,创建这个类的实例数组来接收数据。本例中要使用的XML文件如下:
1 2 3 4 5 6 7 8 9 10 11 |
<?xml version="1.0" encoding="utf-8"?> <UserList> <User Name="Liu" ID="1"> <Website><![CDATA[http://svn1.bcoder.com ]]></Website> <Intro>I come from hebei.</Intro> </User> <User Name="Zhang" ID="2"> <Website><![CDATA[http://www.desktoptool.net]]></Website> <Intro>I come from Shandong.</Intro> </User> </UserList> |
所以,在实现解码前我先定义了一个类用于传递XML数据
1 2 3 4 5 6 |
public class UserinfoData { public int ID = 0; public String uName = ""; public String webSite = ""; public String intro = ""; } |
与DOM解析类似,要使用Sax解析必须先创建一个SAXParserFactory,并在此对象中设置一此属性。
1 |
SAXParserFactory saxPF = SAXParserFactory.newInstance(); |
SAXParserFactory创建后使用此对象创建一个SAXParser
1 |
SAXParser saxP = saxPF.newSAXParser(); |
按说这时候我们该用saxP的Parse方法来解析XML了,但是我们还没负责解析的DefaultHanlder类,让我们转过头来创建一个解析某XML的DefaultHanlder类吧。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 |
package com.example.xml_app; import java.util.ArrayList; import java.util.List; import org.xml.sax.Attributes; import org.xml.sax.SAXException; import org.xml.sax.helpers.DefaultHandler; public class UserinfoHandler extends DefaultHandler { //用于在此类中存储解析完的数据 public List<UserinfoData> uData = new ArrayList<UserinfoData>(); //用于在执行某段XML时存储数据 private UserinfoData tmpUData; //用于标志当前正在处理的节点名称 private String curNodeName = ""; @Override public void characters(char[] ch, int start, int length) throws SAXException { super.characters(ch, start, length); String str = new String(ch, start, length); if (tmpUData != null){ if (curNodeName.equals("Website")) { tmpUData.webSite = tmpUData.webSite.concat(str); } else if (curNodeName.equals("Intro")) { tmpUData.intro = tmpUData.intro.concat(str); } } } @Override public void endDocument() throws SAXException { super.endDocument(); } @Override public void endElement(String uri, String localName, String qName) throws SAXException { //如果是要解析的节点读取结束,将用于存储局部数据的变量赋值为null if (localName.equals("User")){ uData.add(tmpUData); tmpUData = null; } super.endElement(uri, localName, qName); } @Override public void startDocument() throws SAXException { super.startDocument(); } @Override public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { //某节点开始创建存储局部数据的对象 //读取该节点的属性值 if (localName.equals("User")){ if (tmpUData == null){ tmpUData = new UserinfoData(); tmpUData.ID = Integer.parseInt(attributes.getValue("ID")); tmpUData.uName = attributes.getValue("Name"); } } //某个节点开始时,将该节点的名称存储在临时变量中 curNodeName = localName; super.startElement(uri, localName, qName, attributes); } } |
注意:在characters中,我们使用的是tmpUData.webSite = tmpUData.webSite.concat(str);,并不是将str直接赋给tmpUData.webSite, 这是因为character并不一定能将节点内的数据一次全部读取完毕,对于长数据是分块一点一点读进来的,所以如果是直接赋值可能造成只取到了最后一部分数据。
用于解析的DefaultHandler类创建好后,我们就可以继续来解析XML文件了,具体代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
public void ParseFromSax(View V) throws ParserConfigurationException, SAXException, NotFoundException, IOException{ EditText etXmlValues = (EditText)findViewById(R.id.editText1); SAXParserFactory saxPF = SAXParserFactory.newInstance(); SAXParser saxP = saxPF.newSAXParser(); UserinfoHandler uHandle = new UserinfoHandler(); saxP.parse(getResources().openRawResource(R.raw.sample_xml), uHandle); List<UserinfoData> uData = uHandle.uData; for(int i=0; i < uData.size(); i++){ etXmlValues.append("ID:" + uData.get(i).ID); etXmlValues.append("rn"); etXmlValues.append("Name:" + uData.get(i).uName); etXmlValues.append("rn"); etXmlValues.append("Website:" + uData.get(i).webSite); etXmlValues.append("rn"); etXmlValues.append("Intro:" + uData.get(i).intro); etXmlValues.append("rn"); } } |