SAX解析
如果要用SAX来解析xml文档,则需要一个类来继承android系统提供的ContentHandler类。但是如果继承ContentHandler这个类,即使你不使用这个类提供的所有方法,你也必须实现其内部的所有方法(一般情况下没有使用的方法可以直接用空方法代替),但是这样开发起来不是很方便。因此我们可以改为继承DefaultHandler这个类,这样的话我们只需要实现程序中所需要的方法即可,其它的方法这个类内部其实已经用空方法代替了。
- ContentHandler接口的方法有以下几种:
- voidstartDocument();
- voidendDocument();
- voidstartElement(Stringuri,StringlocalName,StringqName,Attributesatts);
- voidendElement(Stringuri,0); background-color:inherit">//标签解析结束时执行
- voidcharacters(char[]ch,intstart,153); font-weight:bold; background-color:inherit">intlength);
android中使用SAX来解析xml文件,需先建立一个SAX工厂,即SAXParserFactory对象,还需建立一个XMLReader对象,该类绑定ContentHandler子类,且与xml源文件结合在一起。即其处理过程为创建事件处理程序,创建SAX解析器,键事件处理程序分配给解析器,对文档进行解析,将每个事件发送给处理程序。
1.在src目录下新建一个android.xml文件
<?xmlversion="1.0"encoding="UTF-8"?>
- <persons>
- personid="23">
- name>xiaanming</age>23personpersonid="20">liudehua>28>
2.新建一个Person.class用来存放解析的对象
packagecom.example.xml_parser;
-
- publicclassPerson{
- privateintid;
- privateStringname;
- intage;
-
- publicPerson(){}
- publicPerson(intid,Stringname,153); font-weight:bold; background-color:inherit">intage){
- this.id=id;
- this.name=name;
- this.age=age;
- }
- intgetId(){
- returnid;
- voidsetId(intid){
- publicStringgetName(){
- returnname;
- voidsetName(Stringname){
- this.name=name;
- intgetAge(){
- returnage;
- voidsetAge( @Override
- publicStringtoString(){
- return"id="+id+",name"+name+",age="+age;
- }
- }
3.新建一个SAXforHandler类继承DefaultHandler,而DefaultHandler实现了ContentHandler接口,需要重写我们需要的方法
importjava.io.BufferedReader;
- importjava.io.IOException;
- importjava.io.InputStream;
- importjava.io.InputStreamReader;
- importjava.util.ArrayList;
- importjava.util.List;
- importjavax.xml.parsers.SAXParser;
- importjavax.xml.parsers.SAXParserFactory;
- importorg.xml.sax.Attributes;
- importorg.xml.sax.InputSource;
- importorg.xml.sax.SAXException;
- importorg.xml.sax.XMLReader;
- importorg.xml.sax.helpers.DefaultHandler;
- importandroid.util.Log;
- classSAXforHandlerextendsDefaultHandler{
- staticfinalStringTAG="SAXforHandler";
-
-
- */
- privateList<Person>persons;
- /**
- *Person对象的引用,记录当前的Person
- */
- privatePersonperson;
- *通过此变量,记录当前一个标签的名称
- privateStringtag;
- *此方法只有在开始解析文档的时候执行一次,比较适合处理一些初始化的东西
- *我new了一个ArrayList<Person>()对象和打印Log
- @Override
- voidstartDocument()throwsSAXException{
- persons=newArrayList<Person>();
- Log.i(TAG,"****startDocument*****");
- *文档解析完了调用的回调方法
- voidendDocument()throwsSAXException{
- "****endDocument*****");
- *uri是命名空间
- *localName标签的名称,如name,age等
- *qName带命名空间的标签名
- *Attributes存放改标签的所有属性
- *
- *当localName为person的时候,我们拿出person标签的属性值,此处由于只有一个属性,也可以直接person.setId(Integer.valueOf(attributes.getValue(0)));
- *然后设置tag=person,这个方法执行完了,然后会执行回调方法characters(char[]ch,intstart,intlength),这是一个循环的过程
- if("person".equals(localName)){
- for(inti=0;i<attributes.getLength();i++){
- "attributesName:"+attributes.getLocalName(i)+"__attributesValue:"+attributes.getValue(i));
- person=newPerson();
- person.setId(Integer.valueOf(attributes.getValue(i)));
- tag=localName;
- Log.i(TAG,"localName="+localName);
- *这个方法只要是获取两个标签里面的值的,这里最好用trim()方法过滤下,可以避免读取到的XML有空格带来不必要的麻烦
- *执行完这个方法就执行回调方法endElement(Stringuri,StringqName),这也是一个循环的过程
- intlength)
- Stringdate=newString(ch,start,length).trim();
- if(!"".equals(date)){
- "Content:"+date);
- if("name".equals(tag)){
- person.setName(date);
- }elseif("age".equals(tag)){
- person.setAge(Integer.valueOf(date));
- *uri,localName,qName跟上面的一个意思
- *当localName=person并且person对象为null时,说明一个person对象解析完毕
- *将person加入到List当中
- *每个标签解析完了需要将tag=null
- if("person".equals(localName)&&person!=null){
- persons.add(person);
- null;
- tag=null;
- *拿到成员变量List<Person>persons的方法
- *@return
- publicList<Person>getPersons(){
- returnpersons;
- *1.加载需要解析的文件,因为XML放在src目录下,可以通过类装载器的方法获得文件路径,在以输入流的方式加入解析器
- *2.解析XML有两种形式,创建一个XMLReader或者直接使用XMLParser
- *@throwsException
- staticList<Person>sax_XML()throwsException{
- InputStreamis=MainActivity.class.getClassLoader().getResourceAsStream("android.xml");
- <spanstyle="font-size:32px;color:#ff0000;">
- </span>
- SAXforHandlersaXforHandler=newSAXforHandler();
- SAXParserFactoryspf=SAXParserFactory.newInstance();
- SAXParsersaxParser=spf.newSAXParser();
- //使用XMLReader的方式
- //XMLReaderxmlReader=saxParser.getXMLReader();
- //xmlReader.setContentHandler(saXforHandler);
- //xmlReader.parse(newInputSource(is));
- //直接使用XMLParser,推荐使用这种
- saxParser.parse(is,saXforHandler);
- //获取解析好了的List对象
- List<Person>list=saXforHandler.getPersons();
- is.close();
- returnlist;
- *测试方法,根据输入流获取里面的内容
- *@paramis
- *@throwsIOException
- staticStringgetInputStreamContent(InputStreamis)throwsIOException{
- StringBuffersb=newStringBuffer();
- BufferedReaderbr=newBufferedReader(newInputStreamReader(is));
- Stringline;
- while((line=br.readLine())!=null){
- sb.append(line);
- br.close();
- returnsb.toString();
- }
DOM解析 DOM比SAX更容易掌握,因为她没有涉及回调和复杂的状态管理,然而,DOM的实现常常将所有的XML节点保存在内存中,这样使的处理较大的文档效率低。
XML基本的节点类型
node - DOM基本的数据类型
Element - 最主要处理的对象是Element
Attr - 元素的属性
Text - 一个Element 或者Attr的实际内容
Document - 代表整个XML文档,一个Document对象通常也称为一颗DOM树
1 新建一个DomPersonService.class,注释我写的清楚,大家自己看
packagecom.example.dom_parser;
- importjava.util.ArrayList;
- importjava.util.List;
- importjavax.xml.parsers.DocumentBuilder;
- importjavax.xml.parsers.DocumentBuilderFactory;
- importorg.w3c.dom.Document;
- importorg.w3c.dom.Element;
- importorg.w3c.dom.Node;
- importorg.w3c.dom.NodeList;
- classDomPersonService{
- staticList<Person>readXML()throwsThrowable{
- //获得android.xml文件的输入流
- List<Person>persons=newArrayList<Person>();
- //实例化DocumentBuilderFactory和DocumentBuilder,并创建Document
- DocumentBuilderFactoryfactory=DocumentBuilderFactory.newInstance();
- DocumentBuilderbuilder=factory.newDocumentBuilder();
- Documentdocument=builder.parse(is);
- //返回文档的根(root)元素
- ElementrootElement=document.getDocumentElement();
- //获取一个Note(DOM基本的数据类型)集合,这里有两个personNote
- NodeListnodes=rootElement.getElementsByTagName("person");
- //遍历Note集合
- 0;i<nodes.getLength();i++){
- //先从第一个person元素开始解析
- ElementpersonElement=(Element)nodes.item(i);
- Personperson= person.setId(Integer.valueOf(personElement.getAttribute("id")));
- //获取person下面的name和age的Note集合
- NodeListchileNodes=personElement.getChildNodes();
- inty=0;y<chileNodes.getLength();y++){
- NodechildNode=chileNodes.item(y);
- //判断子Note的类型为元素Note
- if(childNode.getNodeType()==Node.ELEMENT_NODE){
- ElementchildElement=(Element)childNode;
- if("name".equals(childElement.getNodeName())){
- person.setName(childElement.getFirstChild().getNodeValue());
- if("age".equals(childElement.getNodeName())){
- person.setAge(Integer.valueOf(childElement.getFirstChild().getNodeValue()));
- Log.e("log",person.toString());
- returnpersons;
- }
关于DOM解析XML,我们要清楚的知道个节点之间的关系,才能更好的操作对象树,值得注意的是在建立Element时,要注意jar包的导入, 要选择org.w3c.dom.Element,而不是其他的包.
Pull解析
1.Pull简介
Pull解析器是Android系统内置的的,Pull解析器与SAX解析器类似,他提供了类似的事件,如开始元素和介绍元素的事件,使用parser.next()可以进入下一个元素并触发相应的事件,然后进行相应的处理,当元素开始解析时,调用perser.nextText()方法就可以获取到下一个Text类型元素的值。
2.pull特点
一.简单的结构,一个接口,一个另外,一个工厂组成了Pull解析器
二.简单易用,Pull解析器只有一个重要的方法next(),他被用来检索下一个事件,而他的事件也仅仅只有五个,START_DOCUMENT,START_TAG,TEXT,END_TAG,END_DOCUMENT
三.最小的内存消耗,Pull解析器和SAX解析器一样,对内存的暂用少,但是SAX解析稍微有点繁琐,DOM很耗内存,所以Pull被推荐使用
3,示例 Pull解析XML
新建一个PullXMLService
packagecom.example.pull_parser;
- importorg.xmlpull.v1.XmlPullParser;
- importandroid.util.Xml;
- classPullXMLService{
- throwsException{
- //获取src目录下面的android.xml文件的输入流
- InputStreamis=PullXMLService.//用来存放解析的Person对象
- List<Person>persons=//一个标记
- booleanflag=false;
- Personperson=//实例化一个XmlPullParser对象
- XmlPullParserparser=Xml.newPullParser();
- //设置输入流和编码
- parser.setInput(is,"UTF-8");
- //触发了第一个事件,根据XML的语法,也就是从他开始了解文档
- inteventCode=parser.getEventType();
- //如果获得的事件码如果是文档的结束,那么解析结束
- while(eventCode!=XmlPullParser.END_DOCUMENT){
- switch(eventCode){
- caseXmlPullParser.START_DOCUMENT:{
- //开始解析的时候我们一般做一些初始化的操作
- persons=break;
- caseXmlPullParser.START_TAG:{
- //判断当前的元素是否是需要检索的元素
- if("person".equals(parser.getName())){
- flag=true;
- person.setId(Integer.valueOf(parser.getAttributeValue(0)));
- if(flag){
- if("name".equals(parser.getName())){
- person.setName(parser.nextText());
- }if("age".equals(parser.getName())){
- person.setAge(Integer.valueOf(parser.nextText()));
- caseXmlPullParser.END_TAG:{
- if("person".equals(parser.getName())&&person!= flag= Log.e("log",person.toString());
- person=break;
- //这一步很重要,该方法返回一个事件码,也是触发下一个事件的方法
- eventCode=parser.next();
- }
好了,这样子就解析完了android.xml 是不是很方便很简单呢,比SAX和DOM要更容易理解。 (编辑:李大同)
【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!
|