Android XML文档解析(一)——SAX解析

标签: android xml 文档 | 发表时间:2013-09-22 23:50 | 作者:luzhenrong45
出处:http://blog.csdn.net

  ------------------------------------------------------------------------------------------------------

       此文章仅作为学习交流所用

       转载或引用请务必注明原文地址:

        http://blog.csdn.net/luzhenrong45/article/details/11851607      

       或联系作者:[email protected] 

       谢谢!                       

     ------------------------------------------------------------------------------------------------------

  

 一. XML介绍

    XML:extensible markup language,可扩展标记语言. 与HTML(超文本标记语言,即Hypertext Markup Language)一样,XML也是 标准通用标记语言 (SGML) 的子集,非常适合 Web 传输。XML与HTML的设计区别是:XML 被设计为传输和存储数据,其焦点是数据的内容。而HTML 被设计用来显示数据,其焦点是数据的外观。HTML 旨在显示信息,而 XML 旨在传输信息。XML 提供统一的方法来描述和交换独立于应用程序或供应商的结构化数据。其目的是为了促进Internet上结构化文档的交换。简单的说,XML是一组规则和准则的集合,用于以无格式文本来描述结构化数据.

    XML是纯数据描述,与编程语言、操作系统或传输协议无关,从而将数据从以代码为中心的基础结构所产生的约束中解放出来,让数据能够在Web上更自由的流通。然而XML本身只是以纯文本对数据进行编码的一种格式,要想利用XML,或者说利用XML文件中所编码的数据,必须先将数据从纯文本中解析出来,因此,必须有一个能够识别XML文档中信息的解析器,用来解释XML文档并提取其中的数据。根据数据提取的不同需求,又存在着多种解析方式,不同的解析方式有着各自的优缺点和适用环境。选择合适的XML解析技术能够有效提升应用系统的整体性能.在Android中,常见的XML解析器分别为SAX解析器、DOM解析器和PULL解析器.

    下面,介绍SAX解析方式.

二.  SAX解析

    SAX,全称Simple API for XML,既是指一种接口,也是指一个软件包。SAX解析XML文件采用事件驱动的方式进行,也就是说,SAX是逐行扫描文件,当扫描到文档(document)开始与结束、元素(element)开始与结束、文档(document)结束等地方时回调你写好的事件处理程序,然后继续同样的扫描,直至文档结束。使用SAX的优势在于其解析速度较快,占用内存较少(相对于DOM而言)。而且SAX在解析文件的过程中得到自己需要的信息后可以随时终止解析,并不一定要等文件全部解析完毕。凡事有利必有弊,其劣势在于SAX采用的是流式处理方式,当遇到某个标签的时候,它并不会记录下以前所遇到的标签,也就是说,在处理某个标签的时候,比如在 startElement方法中,所能够得到的信息就是标签的名字和属性,至于标签内部的嵌套结构,上层标签、下层标签以及其兄弟节点的名称等等与其结构相关的信息都是不得而知的。实际上就是把XML文件的结构信息丢掉了,如果需要得到这些信息的话,只能你自己在程序里进行处理了。所以相对DOM而言,SAX处理XML文档没有DOM方便,SAX处理的过程相对DOM而言也比较复杂。

 


 

//用于处理文档解析开始事件

public void startDocument()throws SAXException

//处理元素开始事件,从参数中可以获得元素所在名称空间的uri,元素名称,属性类表等信息

public void startElement(String namespacesURI , String localName , String qName , Attributes atts) throws SAXException

//处理元素结束事件,从参数中可以获得元素所在名称空间的uri,元素名称等信息

public void endElement(String namespacesURI , String localName , String qName) throws SAXException
//处理元素的字符内容,从参数中可以获得内容

public void characters(char[] ch , int start , int length)  throws SAXException

//当文档结束的时候,调用这个方法,可以在其中做一些善后的工作
public void endDocument() throws SAXException 

三. SAX解析XML步骤

Android 使用SAX解析XML文件有两种方式,第一是直接使用SAXParser,或者创建一个XMLReader.不管采用哪种方式,前面三个步骤是一样的.

(一)第一步:加载需要解析的文件,将一个xml文档或者资源变成一个java可以处理的InputStream流.比如我的xml文件名是laolu_xml.xml,放在src目录下,可通过类装载器的方式获得文件路径,再获得文件的输入流

InputStream is= this.getClass().getClassLoader().getResourceAsStream("laolu_xml.xml");

(二)第二步:新建一个工厂类SAXParserFactory

SAXParserFactory factory = SAXParserFactory.newInstance();

(三)第三步:让工厂类产生一个SAX的解析类SAXParser

SAXParser saxParser = factory.newSAXParser();

(四)第四步:可以采用XMLReader解析或直接使用SAXParser解析.

 

 (1)采用XMLReader

1) 从SAXPsrser中得到一个XMLReader实例

XMLReader xmlReader = saxParser.getXMLReader();

2) 把自己写的handler注册到XMLReader中,一般最重要的就是ContentHandler:

SAXForHandler handler = new SAXForHandler ();  //SAXForHandler为自己写的SAX解析类
xmlReader.setContentHandler(handler);
3) 开始解析XML
xmlReader.parse(new InputSource(is));

 

(2)直接使用SAXParser解析

SAXForHandler handler = new SAXForHandler ();
saxParser.parse(is,handler);
 

两种方式都可以对XML文件进行解析,使用的效果是完全一样的.其实SAXParser是JAXP(JAVA API for XML Processing) 对XMLReader的一个封装,只不过,SAXParser能接受更多类型的参数,能方便对不同数据源的XML文档进行解析,使用XMLReader要稍微烦琐一些.

 

四.SAX解析实例.

(一)下面以一个工程实例来实现SAX对XML文件的解析.新建一个xml文件: laolu_xml.xml,该文件放在工程根目录下面.内容如下:

<?xml version="1.0"  encoding="UTF-8"?>
<persons>
    <person id="0">
        <name>刘德华</name>
        <sex>男</sex>
        <age>21</age>
    </person>
    <person id="1">
        <name>张漫玉</name>
        <sex>女</sex>
        <age>22</age>
    </person>
    <person id="2">
        <name>张易谋</name>
        <sex>男</sex>
        <age>23</age>
    </person>
    <person id="3">
        <name>周新驰</name>
        <sex>未知</sex>
        <age>24</age>
    </person>
    <person id="4">
        <name>纳兰容若</name>
        <sex>男</sex>
        <age>25</age>
    </person>
</persons>


(二)先看一下实际效果图,Android对于XML解析,主要有sax,dom,pull三种方式,这里只介绍sax方式.其他两种以后再介绍.

 

(三)工程源码框架

(1)布局文件:

 main_xml.xml  

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
     android:orientation="vertical"
    tools:context=".XML_ParseActivity" >
    
     <TextView
	     android:layout_width="wrap_content"
	     android:layout_height="wrap_content"
	     android:text="@string/hello_world" />
     <Button
	     android:id="@+id/sax_btn" 
	     android:layout_width="match_parent"
	     android:layout_height="wrap_content"
	     android:text="@string/sax_parse"/>
     <Button
         android:id="@+id/dom_btn"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:text="@string/dom_parse"
        />
      <Button   
         android:id="@+id/pull_btn"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:text="@string/pull_parse"
        />  
      <ListView  
         android:id="@+id/listview"  
         android:layout_width="fill_parent"  
         android:layout_height="wrap_content" >  
      </ListView>  
            
    </LinearLayout>
    


listview_xml.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
    android:layout_width="fill_parent"  
    android:layout_height="fill_parent"  
    android:orientation="horizontal" >  
  
    <View  
        android:layout_width="0.5px"  
        android:layout_height="fill_parent"  
        android:background="#B8B8B8"  
        android:visibility="visible" />  
        
     <TextView
         android:id="@+id/id"
         android:layout_width="60dip"
         android:layout_height="40dip"
         />
     <View  
        android:layout_width="0.5px"  
        android:layout_height="fill_parent"  
        android:background="#B8B8B8"  
        android:visibility="visible" />  
        
     <TextView
         android:id="@+id/name"
         android:layout_width="120dip"
         android:layout_height="40dip"
         />
     
     <View  
        android:layout_width="0.5px"  
        android:layout_height="fill_parent"  
        android:background="#B8B8B8"  
        android:visibility="visible" />  
        
     <TextView
         android:id="@+id/sex"
         android:layout_width="60dip"
         android:layout_height="40dip"
         />
     
     <View  
        android:layout_width="0.5px"  
        android:layout_height="fill_parent"  
        android:background="#B8B8B8"  
        android:visibility="visible" />  
        
     <TextView
         android:id="@+id/age"
         android:layout_width="120dip" 
         android:layout_height="40dip"
         />
   
        
</LinearLayout>


(2)这里重写了SimpleAdapter适配器,使用ListView的效果更好看一点.当然,这一点跟今天的主题没关.

MySimpleAdapter.java

package com.laolu.adapter;

import java.util.List;
import java.util.Map;

import android.content.Context;
import android.graphics.Color;
import android.view.View;
import android.view.ViewGroup;
import android.widget.SimpleAdapter;


public class MySimpleAdapter extends SimpleAdapter
{

	public MySimpleAdapter(Context context,
			List<? extends Map<String, ?>> data, int resource, String[] from,
			int[] to) 
	{
		super(context, data, resource, from, to);
	} 

	@Override
	public View getView(int position, View convertView, ViewGroup parent) 
	{
		View view=null;
		if(convertView!=null)
		{
			view=convertView;
		}else
		{
			view=super.getView(position,convertView,parent);
			
		}
		int colors[]={Color.GRAY,Color.WHITE}; 
		view.setBackgroundColor(colors[position%2]);  // 每个item之间颜色不同  
		
		return super.getView(position, view, parent);//返回自己的view
		
	}
	
}


(3)自己实现的SAX解析类SAXForHandler,继承DefaultHandler,而DefaultHandler是实现了ContenHandler的接口的.ContentHandler提供了之前所说的相应的事件方法,所以这个类是最重要的.因为这些回调函数都是自己写代码实现的.

SAXForHandler.java

package com.laolu.parser;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

import android.util.Log;

public class SAXForHandler extends DefaultHandler
{
	private static final String TAG="SAXForHandler";
	private List<Map<String,Object>> persons;
	private Map<String,Object> person;
	
	private String nowWitch;
	public List<Map<String,Object>> getPersons()
	{
		return persons;
	}
	
	@Override
	public void startDocument() throws SAXException {
		persons=new ArrayList<Map<String,Object>>();
		Log.i(TAG,"***startDocument()***");
	}
	@Override
	public void startElement(String uri, String localName, String qName,
			Attributes attributes) throws SAXException 
	{
		if("person".equals(localName))
		{
			for(int i=0;i<attributes.getLength();i++)
			{
				Log.i(TAG,"arrtributes: "+attributes.getLocalName(i)+"_attributes_Value"
			        +attributes.getValue(i));
				person=new HashMap<String,Object>();
				person.put("id", attributes.getValue(i));
				
			}
		}
		nowWitch=localName;
		Log.i(TAG, qName+"***startElement()***");

	}
	@Override
	public void characters(char[] ch, int start, int length) 
			throws SAXException {
		String data=new String(ch,start,length).trim();
		if(!"".equals(data.trim()))
		{
			Log.i(TAG, "content: "+data.trim());
		}
		if("name".equals(nowWitch))
		{
			person.put("name", data.trim());
		}else if("age".equals(nowWitch))
		{
			person.put("age", data.trim());
		}else if("sex".equals(nowWitch))
		{
			person.put("sex", data.trim());
		}

	}
	
	@Override
	public void endElement(String uri, String localName, String qName)
			throws SAXException {
		Log.i(TAG,qName+"***endElement()***");
		if("person".equals(localName))
		{
			persons.add(person);
			person=null;
		}
		nowWitch=null;
	}
	@Override
	public void endDocument() throws SAXException {
		Log.i(TAG, "***endDocument()***");
	}
	  
}


(4)主Activity,按下按键,ListView显示解析结果.

package com.laolu.main;

import java.io.InputStream;
import java.util.List;
import java.util.Map;

import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import com.example.xml.R;
import com.laolu.adapter.MySimpleAdapter;
import com.laolu.parser.SAXForHandler;

import android.os.Bundle;
import android.app.Activity;
import android.util.Log;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ListView;
import android.widget.SimpleAdapter;
import android.widget.TextView;

public class XML_ParseActivity extends Activity
{
	private static final String SAX="SAX_Parse";
	private static final String DOM="DOM_Parse";
	private static final String PULL="Pull_Parse";
	ListView listView;

	@Override
	protected void onCreate(Bundle savedInstanceState) 
	{
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main_xml);
		listView=(ListView) findViewById(R.id.listview);
		
		Button saxButton=(Button) findViewById(R.id.sax_btn);
		Button domButton=(Button) findViewById(R.id.dom_btn);
		Button pullButton=(Button) findViewById(R.id.pull_btn);
		saxButton.setOnClickListener(new MyListener());
		domButton.setOnClickListener(new MyListener());
		pullButton.setOnClickListener(new MyListener());
	}
	
	public class MyListener implements OnClickListener
	{

		@Override
		public void onClick(View v)
		{
			switch (v.getId())
			{
			case R.id.sax_btn:
				try{
					updateListViewBySAX();
				}catch(Exception e)
				{
					Log.i(SAX,"SAX Exception!!!");
				}
				break;
			case R.id.dom_btn:
				break;
			case R.id.pull_btn:
				break;
			
			}
				
		}
		
	}
	public void updateListViewBySAX() throws Exception
	{
		InputStream inputStream = this.getClass().getClassLoader().
		getResourceAsStream("laolu_xml.xml");
		SAXForHandler saxForHandler = new SAXForHandler();
		SAXParserFactory spf = SAXParserFactory.newInstance();
		SAXParser saxParser = spf.newSAXParser();
		saxParser.parse(inputStream, saxForHandler);//采用
		
		
		List<Map<String,Object>> persons = saxForHandler.getPersons();
		SimpleAdapter simpleAdapter=new MySimpleAdapter(this, persons, R.layout.listview_xml, 
	     new String[]{"id","name","sex","age"}, new int[]{R.id.id,R.id.name,R.id.sex,R.id.age});
		listView.setAdapter(simpleAdapter);
		inputStream.close();

	}
	
}


 

 

 

 

 

 

 

 

 

         

作者:luzhenrong45 发表于2013-9-22 15:50:36 原文链接
阅读:58 评论:0 查看评论

相关 [android xml 文档] 推荐:

Android XML文档解析(一)——SAX解析

- - CSDN博客移动开发推荐文章
       此文章仅作为学习交流所用.        转载或引用请务必注明原文地址:.        或联系作者:[email protected] .     XML:extensible markup language,可扩展标记语言. 与HTML(超文本标记语言,即Hypertext Markup Language)一样,XML也是 标准通用标记语言 (SGML) 的子集,非常适合 Web 传输.

Android PULL解析XML

- - CSDN博客移动开发推荐文章
int eventType = parser.getEventType();//产生第一个事件. while(eventType!=XmlPullParser.END_DOCUMENT){//只要不是文档结束事件. String name = parser.getName();//获取解析器当前指向的元素的名称.

Android DOM解析XML

- - CSDN博客移动开发推荐文章
if(personChilds.item(y).getNodeType()==Node.ELEMENT_NODE){//判断当前节点是否是元素类型节点. 作者:jaycee110905 发表于2013-2-7 21:04:29 原文链接. 阅读:78 评论:0 查看评论.

文档抽象模型xml,xml解析生成pdf,word文档

- - CSDN博客推荐文章
            

根据对象生成XML文档

- - 企业架构 - ITeye博客
使用Java提供的java.beans.XMLEncoder. 和java.beans.XMLDecoder类. 一、生成的xml文件如下:AStudent.xml. 二、描述学生的JavaBean. * 描述学生的JavaBean.    sb.append("姓名:").append(this.name).append(";   ");.

android 或者java SAX解析XML

- - ITeye博客
本实例解析xml使用的是继承DefaultHandler类,此类就是java中封装好的xml解析器类,下面看代码详细说明:. 第一步:首先说明下xml文件,Java Sax解析是按照xml文件的顺序一步一步的来解析,在解析xml文件之前,我们要先了解xml文件的节点的种类,一种是ElementNode,一种是TextNode.

XML to tree XML 树

- Bloger - 博客园-首页原创精华区
前面发了一个 html to tree 再发一个 xml to tree. 版权所有:版权所有(C) 2009. 文件名称:xml2tree.js. 完成日期:2009-12-22. 页:http://www.chaige.net */ var XML2Tree = function (ini) {.

android解析XML总结-SAX、Pull、Dom三种方式

- - CSDN博客移动开发推荐文章
     在android开发中,经常用到去解析xml文件,常见的解析xml的方式有一下三种:SAX、Pull、Dom解析方式. 最近做了一个android版的CSDN阅读器,用到了其中的两种(sax,pull),今天对android解析xml的这三种方式进行一次总结. xml示例(channels.xml)如下:.

Android平台基于Pull方式对XML文件解析及写入

- - CSDN博客推荐文章
           XML技术在跨平台的情况下的数据交互中得到了广泛的应用,假如我们需要开发一个Android应用程序,需要同服务器端进行数据交互,通过XML文件可以很方便的在Android平台和服务器之间进行数据传输,具体实现涉及到对XML文件进行解析及写入的技术. 本文实现在Android平台上基于Pull方式对XML文件解析的技术.

xml sax解析

- - 移动开发 - ITeye博客
最近一直在做接口,主要用对xml的解析用的是sax,下面我对sax的几种写法做了一个测试:. System.out.println("耗时:"+(end-start));. System.out.println("当前 Java 虚拟机中的使用内存量:" + (freeMemory01-freeMemory02) + " 字节");.