Android数据存储——2.文件存储_E_Pull解析XML文档

今天学习Android数据存储——文件存储_Pull解析XML文档 

    如果在一个XML文档中我们只需要前面一部分数据,但是使用SAX方式或DOM方式会对整个文档进行解析,尽管XML文档中后面的大部分数据我们其实都不需要解析,因此这样实际上就浪费了处理资源。使用PULL方式正合适。

    Pull解析器和SAX解析器虽有区别但也有相似性。他们的区别为:SAX解析器的工作方式是自动将事件推入注册的事件处理器进行处理,因此你不能控制事件的处理主动结束;而Pull解析器的工作方式为允许你的应用程序代码主动从解析器中获取事件,正因为是主动获取事件,因此可以在满足了需要的条件后不再获取事件,结束解析。这是他们主要的区别。

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

    Android系统中和Pull方式相关的包为org.xmlpull.v1,在这个包中提供了Pull解析器的工厂类XmlPullParserFactory和Pull解析器XmlPullParser,XmlPullParserFactory实例调用newPullParser方法创建XmlPullParser解析器实例,接着XmlPullParser实例就可以调用getEventType()和next()等方法依次主动提取事件,并根据提取的事件类型进行相应的逻辑处理。


XMLPULL解析就相当于是Android中的JDOM和DOM4J


    //创建XmlPullParser,有两种方式:
    //方式一:使用工厂类XmlPullParserFactory   
    XmlPullParserFactory pullFactory = XmlPullParserFactory.newInstance();   
    XmlPullParser xmlPullParser = pullFactory.newPullParser();   
    //方式二:使用Android提供的实用工具类android.util.Xml  
    XmlPullParser xmlPullParser = Xml.newPullParser(); 

    XmlPullParser.setInput(InputStream inputStream, String inputEncoding) 解析对应的输入文件

    XmlPullParser.getEventType() 得到元素

    判断元素是否是START_DOCUMENT、END_DOCUMENT、START_TAG、END_TAG、TEXT中的那种,进行相应解析。
    PULL方式比较简单,而且可以根据判断停止解析(DOM和SAX都需要对文件的文章解析中途不能停止)。

XmlPullParserFactory类的常用方法

XmlPullParser的事件代码及常用方法

XmlSerializer接口的常用方法


实例:Pull读取\mnt\sdcard\mldndata\member.xml

XML布局:

<TableLayout 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"
    tools:context=".MyDOMDemo" >
    <TableRow >
        <TextView
        	android:layout_width="match_parent"
        	android:layout_height="wrap_content"
        	android:textSize="20sp"
        	android:text="姓名:"/>
        <TextView
            android:id="@+id/name"
        	android:layout_width="match_parent"
        	android:layout_height="wrap_content"/>
    </TableRow>
    <TableRow >
        <TextView
        	android:layout_width="match_parent"
        	android:layout_height="wrap_content"
        	android:textSize="20sp"
        	android:text="邮箱:"/>
        <TextView
            android:id="@+id/email"
        	android:layout_width="match_parent"
        	android:layout_height="wrap_content"/>
    </TableRow>
    <TableRow >
        <Button
            android:id="@+id/but"
        	android:layout_width="match_parent"
        	android:layout_height="wrap_content"
        	android:text="读取"/>
    </TableRow>
</TableLayout>
Java代码:

保存数据的类:

/**
 * LinkMan保存数据的类
 */
public class LinkMan {
	private String name;
	private String email;
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getEmail() {
		return email;
	}
	public void setEmail(String email) {
		this.email = email;
	}
}
Pull解析工具类:

/**
 * XMLPull工具类
 */
public class MyXMLPullUtil {
	private InputStream input = null;
	public MyXMLPullUtil(InputStream input){
		this.input = input;
	}
	/** 
	 * 接收一个XML文件输入流, 从输入流中读所有LinkMan节点, 将数据封装成对象装入List返回 
	 * @param  input XML文件的输入流 
	 * @return LinkMan对象的集合 
	 * @throws Exception  
	 */ 
	public List<LinkMan> getAllLinkMan() throws Exception{
		List<LinkMan> all = null;	//保存多条数据
		LinkMan man = null;	//保存一条数据
		String elementName = null;	//保存节点的名称
		XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
		XmlPullParser xpp = factory.newPullParser();
		xpp.setInput(this.input, "UTF-8");	//设置输入流以及编码
		int eventType = xpp.getEventType();	//取得事件码
		while(eventType!=XmlPullParser.END_DOCUMENT){	//不是文档底部
			if(eventType==XmlPullParser.START_DOCUMENT){	//文档开始
				all = new ArrayList<LinkMan>();	//初始化LinkMan集合
			}
			else if(eventType==XmlPullParser.START_TAG){	//元素标记开始
				elementName=xpp.getName();	//取得元素名称 
				if("linkman".equals(elementName)){
					man = new LinkMan();
				}
			}
			else if(eventType==XmlPullParser.END_TAG){	//结束元素
				elementName=xpp.getName();	//取得节点名称
				if("linkman".equals(elementName)){
					all.add(man);
					man=null;
				}	
			}
			else if(eventType==XmlPullParser.TEXT){	//数据
				if("name".equals(elementName)){
					man.setName(xpp.getText());
				}
				else if("email".equals(elementName)){
					man.setEmail(xpp.getText());
				}
			}
			eventType=xpp.next();	//取得下一个事件码
		}
		return all;
	}
}
Pull解析XML测试:

public class MyXMLPullDemo extends Activity {
	private TextView name = null;
	private TextView email = null;
	private Button but = null; 
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		super.setContentView(R.layout.main);
		this.name=(TextView)super.findViewById(R.id.name);
		this.email=(TextView)super.findViewById(R.id.email);
		this.but=(Button)super.findViewById(R.id.but);
		this.but.setOnClickListener(new OnClickListenerImpl());
	}
	private class OnClickListenerImpl implements OnClickListener{
		@Override
		public void onClick(View v) {
			/**
			 * Pull读取xml文件
			 */
			if(!Environment.getExternalStorageState().equals(
					Environment.MEDIA_MOUNTED)){//SD卡不存在则不操作
				return;//返回到程序的被调用处 
			}
			File file = new File(Environment.getExternalStorageDirectory()
					+File.separator+"mldndata"+File.separator
					+"member.xml");//要输出的文件路径
			if(!file.exists()){//文件不存在
				return;
			}
			try {
				InputStream input = new FileInputStream(file);
				MyXMLPullUtil util = new MyXMLPullUtil(input); 
				List<LinkMan> all = util.getAllLinkMan();
				MyXMLPullDemo.this.name.setText(all.get(0).getName());
				MyXMLPullDemo.this.email.setText(all.get(0).getEmail());
			}  
			catch (Exception e) {
				e.printStackTrace();
			}
		}
	}
}
读取结果:

实例:Pull输出\mnt\sdcard\mldndata\member.xml

Java代码:

Pull输出XML工具类:

/**
 * Pull输出XML工具类,是将所有要保存的数据都使用List集合定义。
 */
public class MyXMLPullUtil {
	private List<LinkMan> all = null;
	private OutputStream output = null;
	public MyXMLPullUtil(OutputStream output, List<LinkMan> all){
		this.output = output;
		this.all = all;
	}
	public void save() throws Exception{
		XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
		XmlSerializer xs = factory.newSerializer();
		xs.setOutput(this.output, "UTF-8");
		xs.startDocument("UTF-8", true);	//开始文档
		xs.startTag(null, "addresslist");	//开始根元素
		Iterator<LinkMan> iter = this.all.iterator();	
		while(iter.hasNext()){	//用迭代器Iterator遍历List集合
			LinkMan man = iter.next();
			//开始写内部元素
			xs.startTag(null, "linkman");
			
			xs.startTag(null, "name");
			xs.text(man.getName());
			xs.endTag(null, "name");
			
			xs.startTag(null, "email");
			xs.text(man.getEmail());
			xs.endTag(null, "email");
			
			xs.endTag(null, "linkman");
		}
		xs.endTag(null, "addresslist");	//结束根元素
		xs.endDocument();	//结束文档
		xs.flush();	//刷新 输出
	}
	
}
Pull输出XML测试:

public class MyXMLPullDemo extends Activity {
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		super.setContentView(R.layout.main);
		/**
		 * Pull输出xml文件
		 */
		if(!Environment.getExternalStorageState().equals(
				Environment.MEDIA_MOUNTED)){//SD卡不存在则不操作
			return;//返回到程序的被调用处 
		}
		File file = new File(Environment.getExternalStorageDirectory()
				+File.separator+"mldndata"+File.separator
				+"member.xml");//要输出的文件路径
		if(!file.getParentFile().exists()){//文件不存在
			file.getParentFile().mkdirs();//创建文件夹
		}
		List<LinkMan> all = new ArrayList<LinkMan>();
		for(int x= 0;x < 3;x++){
			LinkMan man = new LinkMan();
			man.setName("李兴华 - "+x);
			man.setEmail("mldnqa@163.com");
			all.add(man);
		}
		OutputStream output = null;
		try{
			output = new FileOutputStream(file);
			new MyXMLPullUtil(output, all).save();
		}
		catch (Exception e) {
			e.printStackTrace();
		}
		finally{
			if(output!=null){
				try {
					output.close();
				} 
				catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
}

查看生成文件:

posted @ 2013-04-16 18:23  魅惑之眼  阅读(124)  评论(0编辑  收藏  举报