android_中对xml_进行解析_第1页
android_中对xml_进行解析_第2页
android_中对xml_进行解析_第3页
android_中对xml_进行解析_第4页
android_中对xml_进行解析_第5页
已阅读5页,还剩10页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、DOM解析器是通过将XML文档解析成树状模型并将其放入内存来完成解析工作的,而后对文档的操作都是在这个树状模型上完成的。这个在内存中的文档树将是文档实际大小的几倍。这样做的好处是结构清除、操作方便,而带来的麻烦就是极其耗费系统资源。而SAX正好克服了DOM的缺点,分析能够立即开始,而不是等待所有的数据被处理。而且,由于应用程序只是在读取数据时检查数据,因此不需要将数据存储在内存中,这对于大型文档来说是个巨大的优点。事实上,应用程序甚至不必解析整个文档;它可以在某个条件得到满足时停止解析。选择 DOM 还是选择 SAX,这取决于下面几个因素:应用程序的目的:如果打算对数据作出更改并将它输出为 X

2、ML,那么在大多数情况下,DOM 是适当的选择。并不是说使用 SAX 就不能更改数据,但是该过程要复杂得多,因为您必须对数据的一份拷贝而不是对数据本身作出更改。数据容量: 对于大型文件,SAX 是更好的选择。数据将如何使用:如果只有数据中的少量部分会被使用,那么使用 SAX 来将该部分数据提取到应用程序中可能更好。 另一方面,如果您知道自己以后会回头引用已处理过的大量信息,那么 SAX 也许不是恰当的选择。对速度的需要: SAX 实现通常要比 DOM 实现更快。基于上面的分析,在基于Android系统的内存和CPU资源比较有限的手持设备上,只要我们不需要修改XML数据或者随机的访问XML数据,

3、SAX尽管可能需要更多的编码工作,但是为了更小的内存和CPU消耗,还是值得的。另外,Android SDK中已经包含了JAXP对应的javax.xml.parsers包,和SAX对应org.xml.sax(当然DOM对应的org.w3c.dom包也包含在内),加上Android还提供了android.sax这样的包来方便SAX Handle的开发,基于JAXP和SAX这样的标准方法来开发不仅复杂度不高,即使出现问题在讨论组中寻求解决方案也是比较容易的。android 中的xml解析应该是和java中一条道路 主要分为sax 解析和的Dom 解析。 如下的介绍的相关的包和类均为android 环

4、境下:sax解析对应为:orgxmlsax 包 :xml解析两个主要用于SAXParser的上下文建立示例如下:SAXParserFactory factory = SAXParserFactory.newInstance();SAXParser parser = factory.newSAXParser();ParseXML parX = new ParseXML();parser.parse(F:emps.xml, parX);这里的ParseXML 一般是继承于org.xml.sax.helpers.DefaultHandler类的解析实现。因为Sax 对xml的解析是基于事件类型的,也

5、就是Sax Parser逐步的读取xml文件,然后碰到一个节点,一个属性,碰到一个节点的结束等事件都会回调哦org.xml.sax.helpers.DefaultHandler 之类的实现,然后在Hander 的实现中具体解析各个节点名称,属性名称。通过以上的特点可以看出sax有速度快(不需要全部的读入内存并构建树),消耗的内存较少,线性的从上往下解析,所以它比较的适合于xml文件大,速度要求高,解析结构自上而下 如把html展示出来,xml转为html等。Dom解析对应为:orgw3cdom包:xml的各个元素对应类结构也和sax 一样,最终的解析目标指向org.w3c.dom.Docume

6、nt.示例如下:File docFile = new File(orders.xml);Document doc = null;DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();DocumentBuilder db = dbf.newDocumentBuilder();doc = db.parse(docFile); / get the document.因为Dom 是基于树结构,所以要全部结构内容读入内容,构造树,所以比较花费时间,但是dom 的操作可以反复的来回操作,灵活性比较高,做出的程序结构也比较容易认可

7、,对于那些性能要求不是很高的,内容比较少的,xml上下结构比较复杂的用dom应该是比较好的选择了。因为在开发中,我们会常用到xml文件的读写操作,因为手机操作有很多版本问题和很多小数据在数据库不是良好的解决方案。所以会用到很多xml操作。 android开发一般对xml操作常用三种技术:sax、dom、pull 分别详细的进行介绍: 首先创建开发测试坏境(一下三种方法都会使用这个环境): 在类路径下面创建xml文件: person.xml 王昌龙 23 小妾 17 (我的名字and因为没有媳妇,就假设叫小妾) 针对person创建javabean,(因为我们下面要以对象的形式获取此xml文件内

8、容) package cn.partner4java.xml.bean;public class Person private int id; private String name; private short age; public int getId() return id; public void setId(int id) this.id = id; public String getName() return name; public void setName(String name) = name; public short getAge() return age; public

9、 void setAge(short age) this.age = age; Override public int hashCode() final int prime = 31; int result = 1; result = prime * result + id; return result; Override public boolean equals(Object obj) if (this = obj) return true; if (obj = null) return false; if (getClass() != obj.getClass() return fals

10、e; Person other = (Person) obj; if (id != other.id) return false; return true; sax: SAX是一个解析速度快并且占用内存少的xml解析器,非常适合用于Android等移动设备。 SAX解析XML文件采用的是事件驱动,也就是说,它并不需要解析完整个文档,在按内容顺序解析文档的过程中,SAX会判断当前读到的字符是否合法XML语法中的某部分,如果符合就会触发事件。所谓事件,其实就是一些回调(callback)方法,这些方法(事件)定义在ContentHandler接口。下面是一些ContentHandler接口常用的方

11、法:startDocument()当遇到文档的开头的时候,调用这个方法,可以在其中做一些预处理的工作。endDocument()和上面的方法相对应,当文档结束的时候,调用这个方法,可以在其中做一些善后的工作。 startElement(String namespaceURI, String localName, String qName, Attributes atts) 当读到一个开始标签的时候,会触发这个方法。namespaceURI就是命名空间,localName是不带命名空间前缀的标签名,qName是带命名空间前缀的标签名。通过atts可以得到所有的属性名和相应的值。要注意的是SAX中

12、一个重要的特点就是它的流式处理,当遇到一个标签的时候,它并不会纪录下以前所碰到的标签,也就是说,在startElement()方法中,所有你所知道的信息,就是标签的名字和属性,至于标签的嵌套结构,上层标签的名字,是否有子元属等等其它与结构相关的信息,都是不得而知的,都需要你的程序来完成。这使得SAX在编程处理上没有DOM来得那么方便。endElement(String uri, String localName, String name)这个方法和上面的方法相对应,在遇到结束标签的时候,调用这个方法。characters(char ch, int start, int length) 这个方法

13、用来处理在XML文件中读到的内容,第一个参数为文件的字符串内容,后面两个参数是读到的字符串在这个数组中的起始位置和长度,使用new String(ch,start,length)就可以获取内容。不知道你看懂上面的解释了么?那好,我们动手做一下: 创建XMLContentHandler,如上面说的应该实现 ContentHandler接口,但是我们这里去集成一个它的实现类就OL, package cn.partner4java.sax.service;import java.util.ArrayList;import java.util.List;import org.xml.sax.Attri

14、butes;import org.xml.sax.SAXException;import org.xml.sax.helpers.DefaultHandler;import cn.partner4java.sax.bean.Person;public class XMLContentHandler extends DefaultHandler private List persons; private Person person; private String preTag; public List getPersons() return persons; /这个方法用来处理在XML文件中读到

15、的内容,第一个参数为文件的字符串内容,后面两个参数是读到的字符串在这个数组中的起始位置和长度, /使用new String(ch,start,length)就可以获取内容。 Override public void characters(char ch, int start, int length) throws SAXException String data = new String(ch, start, length); if(name.equals(preTag) person.setName(data); else if(age.equals(preTag) person.setAg

16、e(new Short(data); /这个方法和上面的方法相对应,在遇到结束标签的时候,调用这个方法。 Override public void endElement(String uri, String localName, String qName) throws SAXException if(person.endsWith(localName) & person != null) persons.add(person); person = null; preTag = null; /和上面的方法相对应,当文档结束的时候,调用这个方法,可以在其中做一些善后的工作。 Override p

17、ublic void startDocument() throws SAXException persons = new ArrayList(); /当读到一个开始标签的时候,会触发这个方法。namespaceURI就是命名空间,localName是不带命名空间前缀的标签名, /qName是带命名空间前缀的标签名。通过atts可以得到所有的属性名和相应的值。要注意的是SAX中一个重要的特点就是它的流式处理, /当遇到一个标签的时候,它并不会纪录下以前所碰到的标签,也就是说,在startElement()方法中,所有你所知道的信息,就是标签的名字和属性, /至于标签的嵌套结构,上层标签的名字,是

18、否有子元属等等其它与结构相关的信息,都是不得而知的, /都需要你的程序来完成。这使得SAX在编程处理上没有DOM来得那么方便。 Override public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException /初始化:新建javabean if(person.equals(localName) person = new Person(); person.setId(new Integer(attributes.getValue(0);

19、 preTag = localName; SAX 支持已内置到JDK1.5中,你无需添加任何的jar文件 书写service代码: package cn.partner4java.sax.service;import java.io.InputStream;import java.util.List;import javax.xml.parsers.SAXParser;import javax.xml.parsers.SAXParserFactory;import cn.partner4java.sax.bean.Person;public class SAXService public st

20、atic List readXML(InputStream inStream) try SAXParserFactory spf = SAXParserFactory.newInstance(); SAXParser saxParser = spf.newSAXParser(); /创建解析器 /设置解析器的相关特性,/sax/features/namespaces = true 表示开启命名空间特性 /saxParser.setProperty(/sax/features/namespaces,true); XMLContentHandler handler = new XMLContent

21、Handler(); saxParser.parse(inStream, handler); inStream.close(); return handler.getPersons(); catch (Exception e) e.printStackTrace(); return null; 进行单元测试: package cn.partner4java.sax.junit;import java.io.InputStream;import java.util.List;import android.test.AndroidTestCase;import android.util.Log;i

22、mport cn.partner4java.sax.bean.Person;import cn.partner4java.sax.service.SAXService;public class SAXServiceTest extends AndroidTestCase private static String TAG = SAXServiceTest; public void testReadXML() InputStream inStream = this.getClass().getClassLoader().getResourceAsStream(person.xml); List

23、persons = SAXService.readXML(inStream); for(Person person:persons) System.out.println(person.getName(); Log.i(TAG, person.getName(); sax的集体操作大体就如上,没有什么太难理解的地方,我们重载的那些方法,你不要想着我们是如何去调用的,不是,他是使用的流程装载,也就说会安照我们开始解释的那个几个方法的作用,安步骤自动往下走,并且方法是重复调用的,因为我们xml里面不止一个数据。android的单元测试我这里说一下: 因为单元测试也就是黑盒测试吧,有很好的作用,能够

24、帮助我们去调试代码,避免出现很难解决的复杂错误,因为我们基本都是会每隔方法测试后,再继续往下写。 我们在写j2ee的junit是怎么样的我就不说了, android里面首先,要配置我们的AndroidManifest.xml 上面targetPackage指定的包要和应用的package相同。也就说必须相同,但是我们的单元测试可以放到此包的子包里,外面是不行的。 编写单元测试代码(选择要测试的方法,右键点击“Run As”-“Android Junit Test” ) 你可能看到了我写了两种打印的方法: System.out.println(person.getName();Log.i(TAG

25、, person.getName(); System.out.println在老版本的日志里面是不打印的(我现在用的最新版本可以了),所以只能用 Log。但是这两种打印方式还是都不可以打印中文,会出现乱码DOM: 除了可以使用 SAX解析XML文件,大家也可以使用熟悉的DOM来解析XML文件。 DOM解析XML文件时,会将XML文件的所有内容读取到内存中,然后允许您使用DOM API遍历XML树、检索所需的数据。使用DOM操作XML的代码看起来比较直观,并且,在某些方面比基于SAX的实现更加简单。但是,因为DOM需要将XML文件的所有内容读取到内存中,所以内存的消耗比较大,特别对于运行Andr

26、oid的移动设备来说,因为设备的资源比较宝贵,所以建议还是采用SAX来解析XML文件,当然,如果XML文件的内容比较小采用DOM是可行的。 DOM解析就很常见了,我也就不多说了,但是这个方法是不建议使用的,因为他会加载整个xml文件,会消耗更多的系统资源。 import java.io.InputStream;import java.util.ArrayList;import java.util.List;import javax.xml.parsers.DocumentBuilder;import javax.xml.parsers.DocumentBuilderFactory;import

27、 org.w3c.dom.Document;import org.w3c.dom.Element;import org.w3c.dom.Node;import org.w3c.dom.NodeList;/* * 使用Dom解析xml文件 * */public class DomXMLReader public static List readXML(InputStream inStream) List persons = new ArrayList(); DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();

28、 try DocumentBuilder builder = factory.newDocumentBuilder(); Document dom = builder.parse(inStream); Element root = dom.getDocumentElement(); NodeList items = root.getElementsByTagName(person);/查找所有person节点 for (int i = 0; i items.getLength(); i+) Person person = new Person(); /得到第一个person节点 Element

29、 personNode = (Element) items.item(i); /获取person节点的id属性值 person.setId(new Integer(personNode.getAttribute(id); /获取person节点下的所有子节点(标签之间的空白节点和name/age元素) NodeList childsNodes = personNode.getChildNodes(); for (int j = 0; j childsNodes.getLength(); j+) Node node = (Node) childsNodes.item(j); /判断是否为元素类型

30、 if(node.getNodeType() = Node.ELEMENT_NODE) Element childNode = (Element) node; /判断是否name元素 if (name.equals(childNode.getNodeName() /获取name元素下Text节点,然后从Text节点获取数据 person.setName(childNode.getFirstChild().getNodeValue(); else if (“age”.equals(childNode.getNodeName() person.setAge(new Short(childNode.

31、getFirstChild().getNodeValue(); persons.add(person); inStream.close(); catch (Exception e) e.printStackTrace(); return persons;pull: 除了可以使用 SAX和DOM解析XML文件,大家也可以使用Android内置的Pull解析器解析XML文件。 Pull解析器的运行方式与 SAX 解析器相似。它提供了类似的事件,如:开始元素和结束元素事件,使用parser.next()可以进入下一个元素并触发相应事件。事件将作为数值代码被发送,因此可以使用一个switch对感兴趣的

32、事件进行处理。当元素开始解析时,调用parser.nextText()方法可以获取下一个Text类型元素的值。既然android建议我们使用pull,我就详细的说一下这个方法吧。 创建android工程,配置可以单元测试的环境,然后考入我们上面的javabean和xml文件 创建service:package cn.partner4java.pull.service;import java.io.InputStream;import java.util.List;import cn.partner4java.pull.bean.Person;public class PullService p

33、ublic static List readXML(InputStream inStream) return null; 接下啦我们就书写readXML方法: /获取xmlpull,我们可以使用android给我们提供的一个简单获取类(便于快速获得pull解析器) XmlPullParser parser = Xml.newPullParser(); /进行编码设置,把我们需要解析的内容给他 parser.setInput(inStream, UTF-8); /获取事件,就可以触发第一解析到的字符对应的事件 /他也是采用的流式触发 int enentType = parser.getEvent

34、Type(); /这个方法是把流事件往后退/ parser.next(); List persons = null; Person person = null; /XmlPullParser.END_DOCUMENT:Logical end of the xml document. Returned from getEventType, next() and nextToken() /when the end of the input document has been reached. /就是判断这个事件不为文档末尾事件,我们就循环下去 while(enentType != XmlPullP

35、arser.END_DOCUMENT) /对事件进行判断 switch (enentType) /是否为开始事件,可以进行数据初始化处理 case XmlPullParser.START_DOCUMENT: persons = new ArrayList(); break; /是否为开始元素事件,如 /再往下,处理到person id.也会触发这个事件 /也就是每解析一个字符就会触发这个事件 case XmlPullParser.START_TAG: String tag = parser.getName(); /如果当前为person标签,我们需要获取id值 if(person.equals

36、(tag) person = new Person(); person.setId(new Integer(parser.getAttributeValue(0); else if(person != null) if(name.equals(tag) /parser.nextText(),当前为name下一个节点,为文本 person.setName(parser.nextText(); else if(age.equals(tag) person.setAge(new Short(parser.nextText(); break; /如果解析到person结束元素事件时,我们就把当前的pe

37、rson加到结合中 if (parser.getName().equalsIgnoreCase(person) & person != null) persons.add(person); person = null; enentType = parser.next(); return persons;然后我们对读方法进行单元测试 package cn.partner4java.pull.junit;import java.io.InputStream;import java.util.List;import cn.partner4java.pull.bean.Person;import cn

38、.partner4java.pull.service.PullService;import android.test.AndroidTestCase;public class PullServiceTest extends AndroidTestCase public void readXML() throws Exception InputStream inStream = this.getClass().getClassLoader().getResourceAsStream(person.xml); List persons = PullService.readXML(inStream); for(Person person:persons) System.out.println(person.getId() + : + person.getName(); 使用Pull解析器生成XML文件: 有些时候,我们需要生成一个XML文件,生成XML文件的方法有很多,如:可以只使用一个StringBuilder组拼XML内容,然后把内容写入到文件中;或者使用DOM API生成XML文件,或者也可以使用pull解析器生成XML文件,这里推荐大家使用Pul

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论