天天看点

XML PULL解析

         Pull和Sax类似,都是基于流(stream)操作文件,然后根据节点事件回调开发者编写的处理程序。因为是基于流的处理,因此Pull和Sax都比较节约内存资源,不会象Dom那样要把所有节点以对橡树的形式展现在内存中。 但Pull比Sax更简明,而且不需要扫描完整个流。

         他们的区别为:SAX解析器的工作方式是自动将事件推入注册的事件处理器进行处理,因此你不能控制事件的处理主动结束;而Pull解析器的工作方式为允许你的应用程序代码主动从解析器中获取事件,正因为是主动获取事件,因此可以在满足了需要的条件后不再获取事件,结束解析。这是他们主要的区别。如果在一个XML文档中我们只需要前面一部分数据,但是使用SAX方式或DOM方式会对整个文档进行解析,中间不能终止暂停,尽管XML文档中后面的大部分数据我们其实都不需要解析,因此这样实际上就浪费了处理资源。使用PULL方式正合适。

         Pull解析器也提供了类似SAX的事件,开始文档START_DOCUMENT和结束文档END_DOCUMENT,开始元素START_TAG和结束元素END_TAG,遇到元素内容TEXT等,但需要调用next() 方法提取它们(主动提取事件)。

         Android系统中和Pull方式相关的包为org.xmlpull.v1.         PULL是个开源的项目,源码地址http://www.xmlpull.org/

         经常需要使用的类:

          XmlPullParserFactory              工厂类,用来创建pull解析器

          XmlPullParser                           pull解析器

         XmlPullParserException             异常

          XmlSerializer                               该类用来将指定的对象转化为XML文档

          创建XmlPullParser

          创建XmlPullParser方式有两种:

           方式一:通过XmlPullParserFactory创建   

XmlPullParserFactory xpf = XmlPullParserFactory.newInstance();//构造工厂实例
   XmlPullParser parser = xpf.newPullParser();//创建解析对象
           

           方法二:通过Android.util.Xml类

XmlPullParser parser = Xml.newPullParser();
           

       下面开始用Pull解析

         解析的流程如下:

  (1)取得pull解析器

  (2)设置解析器的输入流

  (3)产生第一个事件

  (4)开始解析

  (5)解析结束

         解析XML文件如下:

<?xml version="1.0" encoding="utf-8"?>
<rivers>
 <river name="灵渠" length="605">
     <introduction>
      灵渠在广西壮族自治区兴安县境内,是世界上最古老的运河之一,有着“世界古代水利建筑明珠”的美誉。灵渠古称秦凿渠、零渠、陡河、兴安运河,于公元前214年凿成通航,距今已2217年,仍然发挥着功用。
     </introduction>
      <imageurl>
      http://www.2cto.com/uploadfile/2012/0228/20120228094142711.jpg
     </imageurl>
   </river>
  
   <river name="胶莱运河" length="200">
     <introduction>
      胶莱运河南起黄海灵山海口,北抵渤海三山岛,流经现胶南、胶州、平度、高密、昌邑和莱州等,全长200公里,流域面积达5400平方公里,南北贯穿山东半岛,沟通黄渤两海。胶莱运河自平度姚家村东的分水岭南北分流。南流由麻湾口入胶州湾,为南胶莱河,长30公里。北流由海仓口入莱州湾,为北胶莱河,长100余公里。
     </introduction>
      <imageurl>
      http://www.2cto.com/uploadfile/2012/0228/20120228094142711.jpg
     </imageurl>
   </river>
  
   <river name="苏北灌溉总渠" length="168">
     <introduction>
      位于淮河下游江苏省北部,西起洪泽湖边的高良涧,流经洪泽,青浦、淮安,阜宁、射阳,滨海等六县(区),东至扁担港口入海的大型人工河道。全长168km。
     </introduction>
      <imageurl>
      http://www.2cto.com/uploadfile/2012/0228/20120228094142711.jpg
     </imageurl>
   </river>
 </rivers>
           

           解析过程:

private List<River> parserXMLPULL(InputStream is)
   {
     List<River> list = null;
     River river = null;
//	   XmlPullParserException
//	   XmlSerializer

//	   方式一:
//	   XmlPullParser parser = Xml.newPullParser();
//	   方法二:
	   XmlPullParserFactory xpf = null;
	   XmlPullParser parser = null;
	   try {
			xpf = XmlPullParserFactory.newInstance();
			parser = xpf.newPullParser();
//          将XML文件以流的形式加入,并设置XML文件的编码方式
//			parser.setInput(InputStrean inputStream, String inputEncoding)
//          parser.setInput(Reader reader)
			parser.setInput(is, "UTF-8");
//          此时文档刚初始化,所以解析的位置在文档的开头
			   
			int type = parser.getEventType();//此时返回0,也就是在START_DOCUMENT
			
//          返回类型START_DOCUMENT,END_DOCUMENT,START_TAG,END_TAG,TEXT
		   while(type!= XmlPullParser.END_DOCUMENT)
		   {
			   switch(type)
			   {
			   case XmlPullParser.START_DOCUMENT:
				   //做一些初始化工作
				   list = new ArrayList<River>();   
				   break;
			   case XmlPullParser.START_TAG:
				   //rivers
				   String name = parser.getName();
				   if(name.equals("river"))
				   {
					   String attrName = parser.getAttributeValue(0);
					   int attrLen = Integer.parseInt(parser.getAttributeValue(1));
					   river = new River();
					   river.setName(attrName);
					   river.setLength(attrLen);
				   } 
				   if(parser.getName().equals("introduction")&&river!=null)
				   {
					   String intro = parser.nextText();
					   river.setIntro(intro);   
				   }
				   if("imageurl".equals(parser.getName())&&river!=null)
				   {
					   String url = parser.nextText();
					   river.setUrl(url);
				   }
					   
				 
				 
				   break;
			   case XmlPullParser.END_TAG:
				   String value = parser.getName();
				   if(value.equals("river")&&river!=null&&list!=null)
				   {
//					   添加对象到list中
					   list.add(river);
					   river = null;
				   }
				   break;
			   }
			  type = parser.next();//当前解析位置结束,指向下一个位置
		   }
		
			
            } catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
	       } catch (XmlPullParserException e) {
		    // TODO Auto-generated catch block
		     e.printStackTrace();
	       }

	  	 return list;	   
   }
           

River 类很简单

package com.liupan.parse;

public class River {
	private String name;
	private int length;
	private String intro;
	private String url;
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getLength() {
		return length;
	}
	public void setLength(int length) {
		this.length = length;
	}
	public String getIntro() {
		return intro;
	}
	public void setIntro(String intro) {
		this.intro = intro;
	}
	public String getUrl() {
		return url;
	}
	public void setUrl(String url) {
		this.url = url;
	}

}
           

            XmlSerializer类的使用

public  String createXML(Writer writer  ,List<River> list) throws Exception
   {
	   XmlSerializer serial =Xml.newSerializer();
	   
	   //设置输出流的位置,本句会抛出异常
	   serial.setOutput(writer);
	   //以下开始创建XML文件
	   
	   serial.startDocument("utf-8", true);//对应之前解析时出现的事件
	   serial.startTag("", "rivers");
	   
	   //将list的内容写入XML文件
	   if(list!=null)
	   {
		   for(River river : list)
		   {
			   //创建river标签
			   serial.startTag("", "river");
			   
			   //为river标签添加属性 name 和length
			   serial.attribute("", "name",river.getName());
			   serial.attribute("", "length",""+river.getLength());
			   
			   serial.startTag("", "introduction");
			   serial.text(river.getIntro());
			   serial.endTag("", "introduction");
			   
			   serial.startTag("", "imageurl");
			   serial.text(river.getUrl());
			   serial.endTag("", "imageurl");
			   
			   serial.endTag("","river");
			   
			   
			   
		   }
	   }

	   serial.endTag("", "rivers");
	   serial.endDocument();
	   
//	   刷新输出的缓冲区
	   writer.flush();
	   //关闭输出流
	   writer.close();
	   return writer.toString();
   }
           

继续阅读