xml解析



XML常用的三种解析

activity_main.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:orientation="vertical"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.example.xmlanalysis.MainActivity" >

    <Button
        android:id="@+id/main_dom_analysis"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="DOM解析" />

    <Button
        android:id="@+id/main_dom_back_analysis "
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="DOM反解析" />

    <Button
        android:id="@+id/main_sax_analysis"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="SAX解析" />

    <Button
        android:id="@+id/main_sax_back_analysis "
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="SAX反解析" />

    <Button
        android:id="@+id/main_pull_analysis"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="PULL解析" />

    <Button
        android:id="@+id/main_pull_back_analysis "
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="PULL反解析" />

</LinearLayout>

在res文件夹创建一个asset文件夹,在asset文件夹创建一个book.xml

<?xml version="1.0" encoding="utf-8"?>
<books>
    <book>
        <id>1</id>
        <name>红楼梦</name>
        <price>34</price>
    </book>
    <book>
        <id>2</id>
        <name>三国演义</name>
        <price>23</price>
    </book>
    <book>
        <id>3</id>
        <name>水浒传</name>
        <price>54</price>
    </book>
    <book>
        <id>4</id>
        <name>西游记</name>
        <price>83</price>
    </book>
</books>
package com.example.xmlanalysis.entity;

public class Book {
	private int bookId;
	private String bookName;
	private double bookPrice;
	public int getBookId() {
		return bookId;
	}
	public void setBookId(int bookId) {
		this.bookId = bookId;
	}
	public String getBookName() {
		return bookName;
	}
	public void setBookName(String bookName) {
		this.bookName = bookName;
	}
	public double getBookPrice() {
		return bookPrice;
	}
	public void setBookPrice(double bookPrice) {
		this.bookPrice = bookPrice;
	}
	public Book(int bookId, String bookName, double bookPrice) {
		super();
		this.bookId = bookId;
		this.bookName = bookName;
		this.bookPrice = bookPrice;
	}
	public Book() {
		super();
	}
	@Override
	public String toString() {
		return "Book [bookId=" + bookId + ", bookName=" + bookName + ", bookPrice=" + bookPrice + "]";
	}
	
}
package com.example.xmlanalysis.util;

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

import com.example.xmlanalysis.entity.Book;

public interface BookXml {
	/**
	 * 获取输入流对象,将其转换成book集合
	 * @param is 输入流对象
	 * @return book集合
	 * @throws Exception
	 */
	public List<Book> getBookList(InputStream is)throws Exception;
	/**
	 * 获取book集合对象,将其转换成String流
	 * @param bookList book集合
	 * @return String流
	 * @throws Exception
	 */
	public String setBookList(List<Book> bookList)throws Exception;
}

1、DOM解析

DOM是基于树形结构的的节点或信息片段的集合,允许开发人员使用DOM API遍历XML树、检索所需数据。分析该结构通常需要加载整个文档和构造树形结构,然后才可以检索和更新节点信息。由于DOM在内存中以树形结构存放,因此检索和更新效率会更高。但是对于特别大的文档,解析和加载整个文档将会很耗资源。

整个文档是一个节点文档,每一个XML标签是一个元素节点,包含在XML元素中的文本是文本节点,每一个XML属性是一个属性节点

package com.example.xmlanalysis.util;

import java.io.InputStream;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.List;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import com.example.xmlanalysis.entity.Book;

public class DOMUtil implements BookXml {

	/**
	 * DOM实际上就是document解析,通过文档工厂获取文档对象,并对文档对象的各个节点进行访问
	 */
	@Override
	public List<Book> getBookList(InputStream is) throws Exception {
		List<Book> bookList = new ArrayList<Book>();
		// 创建文档加载工厂,相当于单例的方法
		DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
		// 实例化文档加载对象
		DocumentBuilder db = dbf.newDocumentBuilder();
		// 解析输入流获取文档对象
		Document d = db.parse(is);
		// 获取文档元素对象
		Element element = d.getDocumentElement();
		// 获取名称为book的所有节点集合
		NodeList nl = element.getElementsByTagName("book");
		for (int i = 0; i < nl.getLength(); i++) {
			Book book = new Book();
			Node bookNode = nl.item(i);
			NodeList bookEntity = bookNode.getChildNodes();
			for (int j = 0; j < bookEntity.getLength(); j++) {
				Node bookEntityNode = bookEntity.item(j);
				String nodeName = bookEntityNode.getNodeName();
				if (nodeName.equals("id")) {
					book.setBookId(Integer.valueOf(bookEntityNode
							.getFirstChild().getNodeValue()));
				} else if (nodeName.equals("name")) {
					book.setBookName(bookEntityNode.getFirstChild()
							.getNodeValue());
				} else if (nodeName.equals("price")) {
					book.setBookPrice(Double.valueOf(bookEntityNode
							.getFirstChild().getNodeValue()));
				}
			}
			bookList.add(book);
		}
		return bookList;
	}

	@Override
	public String setBookList(List<Book> bookList) throws Exception {
		// 创建文档加载工厂,相当于单例的方法
		DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
		// 实例化文档加载对象
		DocumentBuilder db = dbf.newDocumentBuilder();
		//获取单例的document文档对象
		Document d=db.newDocument();
		//创建xml总结点books,并返回该节点对象
		Element element=d.createElement("books");
		for (Book book:bookList) {
			Element bookElement=d.createElement("book");
			//采用setAttribute方式会将该节点作为头结点的内部节点
			bookElement.setAttribute("id", book.getBookId()+"");
			//通过setTextContent方式将该节点放入book节点
			Element nameElement=d.createElement("name");
			nameElement.setTextContent(book.getBookName());
			bookElement.appendChild(nameElement);
			//通过setTextContent方式将该节点放入book节点
			Element priceElement=d.createElement("name");
			priceElement.setTextContent(book.getBookPrice()+"");
			bookElement.appendChild(priceElement);
			//将构造好的book节点作为外部节点books的子节点
			element.appendChild(bookElement);
		}
		//将books节点作为整个文档的总结点
		d.appendChild(element);
		//通过单例模式构造TransformerFactory
		TransformerFactory tf=TransformerFactory.newInstance();
		Transformer t=tf.newTransformer();
		t.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
		t.setOutputProperty(OutputKeys.INDENT, "yes");
		t.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "no");
		
		StringWriter writer=new StringWriter();
		//表明文档来源是document
		Source source=new DOMSource(d);
		Result result=new StreamResult(writer);
		
		// 开始转换
		t.transform(source, result);
		return writer.toString();
	}

}

2、SAX解析

SAX(Simple API for XML)解析器是一种基于事件的解析器,它的核心是事件处理模式,主要是围绕着事件源以及事件处理器来工作的。当事件源产生事件后,调用事件处理器相应的处理方法,一个事件就可以得到处理。在事件源调用事件处理器中特定方法的时候,还要传递给事件处理器相应事件的状态信息,这样事件处理器才能够根据提供的事件信息来决定自己的行为。SAX解析器的优点是解析速度快,占用内存少。非常适合在Android移动设备中使用。

package com.example.xmlanalysis.util;

import java.util.ArrayList;
import java.util.List;

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

import com.example.xmlanalysis.entity.Book;
/**
 * 类似于适配器,将装配进来的inputstream转换成我们需要的格式
 * @author Administrator
 *
 */
public class MyHandler extends DefaultHandler{
	private List<Book> bookList;
	private Book book;
	private StringBuilder builder;
	/**
	 * 调用该方法将解析后的数据结构返回到外部调用
	 * @return
	 */
	public List<Book> getBookList(){
		return bookList;
	}
	/**
	 * 当文件开始扫描的时候,初始化存储集合和字符串缓冲流
	 */
	@Override
	public void startDocument() throws SAXException {
		// TODO Auto-generated method stub
		super.startDocument();
		bookList=new ArrayList<Book>();
		builder=new StringBuilder();
	}
	/**
	 * 开始扫描文档内部的每个元素  
	 */
	@Override
	public void startElement(String uri, String localName, String qName,
			Attributes attributes) throws SAXException {
		// TODO Auto-generated method stub
		super.startElement(uri, localName, qName, attributes);
		if (localName.equals("book")) {
			book=new Book();
		}
		//设置字符长度为0,以便重新开始读取元素的字符节点
		builder.setLength(0);
	}
	/**
	 * 将读取的xml内容追加到builder字符串中
	 */
	@Override
	public void characters(char[] ch, int start, int length)
			throws SAXException {
		// TODO Auto-generated method stub
		super.characters(ch, start, length);
		builder.append(ch, start, length);
	}
	/**
	 * 扫描接收后,将字符串内容转换成对应的对象
	 */
	@Override
	public void endElement(String uri, String localName, String qName)
			throws SAXException {
		// TODO Auto-generated method stub
		super.endElement(uri, localName, qName);
		if (localName.equals("id")) {
			book.setBookId(Integer.valueOf(builder.toString()));
		}else if (localName.equals("name")) {
			book.setBookName(builder.toString());
		}else if (localName.equals("price")) {
			book.setBookPrice(Double.valueOf(builder.toString()));
		}else if (localName.equals("book")) {
			bookList.add(book);
		}
	}
}
package com.example.xmlanalysis.util;

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

import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Result;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.sax.SAXTransformerFactory;
import javax.xml.transform.sax.TransformerHandler;
import javax.xml.transform.stream.StreamResult;

import org.xml.sax.helpers.AttributesImpl;

import com.example.xmlanalysis.entity.Book;

public class SAXUtil implements BookXml{

	@Override
	public List<Book> getBookList(InputStream is) throws Exception {
		//SAX解析工厂类
		SAXParserFactory spf=SAXParserFactory.newInstance();
		//SAX解析对象
		SAXParser sp=spf.newSAXParser();
		//构造自定义handler
		MyHandler my=new MyHandler();
		sp.parse(is, my);
		return my.getBookList();
	}

	@Override
	public String setBookList(List<Book> bookList) throws Exception {
		//通过单例模式构造SAXTransformerFactory
		SAXTransformerFactory stf=(SAXTransformerFactory) TransformerFactory.newInstance();
		//构造SAX构造器
		TransformerHandler th=stf.newTransformerHandler();
		//获取文档格式对象
		Transformer t=th.getTransformer();
		t.setOutputProperty(OutputKeys.ENCODING, "utf-8");
		t.setOutputProperty(OutputKeys.INDENT, "yes");
		t.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "no");
		StringWriter sw=new StringWriter();
		Result result=new StreamResult(sw);
		th.setResult(result);
		//uri代表我们的命名空间
		String uri="";
		//设置命名空间的本地名称   
		String localName="";
		th.startDocument();
		th.startElement(uri, localName, "books", null);
		//负责存放元素属性
		AttributesImpl ai=new AttributesImpl();
		char[] ch=null;
		for (Book book : bookList) {
			//每扫描一次对象,就要清空来源属性
			ai.clear();
			ai.addAttribute(uri, localName, "id", "string", String.valueOf(book.getBookId()));
			th.startElement(uri, localName, "book", ai);
			
			
			//将book中的name字段的值转换成字符数组
			th.startElement(uri, localName, "name", null);
			ch=String.valueOf(book.getBookName()).toCharArray();
			th.characters(ch, 0, ch.length);
			th.endElement(uri, localName, "name");
			
			th.startElement(uri, localName, "price", null);
			ch=String.valueOf(book.getBookName()).toCharArray();
			th.characters(ch, 0, ch.length);
			th.endElement(uri, localName, "price");
			
			th.endElement(uri, localName, "book");
		}
		th.endElement(uri, localName, "books");
		th.endDocument();
		return sw.toString();
	}

}

3、PULL解析
PULL解析器的运行方式和SAX类似,都是基于事件的模式。不同的是,在PULL解析过程中,我们需要自己获取产生的事件然后做相应的操作,而不像SAX那样由处理器触发一种事件的方法,执行我们的代码。PULL解析器小巧轻便,解析速度快,简单易用,非常适合在Android移动设备中使用,Android系统内部在解析各种XML时也是用PULL解析器。

package com.example.xmlanalysis.util;

import java.io.InputStream;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.List;

import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlSerializer;

import android.util.Xml;

import com.example.xmlanalysis.entity.Book;

public class PULLUtil implements BookXml{

	@Override
	public List<Book> getBookList(InputStream is) throws Exception {
		List<Book> bookList=null;
		Book book=null;
		//创建PULL解析器
		XmlPullParser xpp=Xml.newPullParser();
		//指明解析器的输入流并指明编码方式
		xpp.setInput(is, "utf-8");
		int eventType=xpp.getEventType();
		//当整个文档扫描还没结束时,不断执行相应的操作
		while (eventType!=XmlPullParser.END_DOCUMENT) {
			switch (eventType) {
			case XmlPullParser.START_DOCUMENT:
				bookList=new ArrayList<Book>();
				break;
			case XmlPullParser.START_TAG:
				if (xpp.getName().equals("book")) {
					book=new Book();
				}else if (xpp.getName().equals("id")) {
					eventType=xpp.next();
					book.setBookId(Integer.valueOf(xpp.getText()));
				}else if (xpp.getName().equals("name")) {
					eventType=xpp.next();
					book.setBookName(xpp.getText());
				}else if (xpp.getName().equals("price")) {
					eventType=xpp.next();
					book.setBookPrice(Double.valueOf(xpp.getText()));
				}
				break;
			case XmlPullParser.END_TAG:
				if (xpp.getName().equals("book")) {
					bookList.add(book);
					book=null;
				}
				break;
			default:
				break;
			}
			eventType=xpp.next();
		}
		return bookList;
	}

	@Override
	public String setBookList(List<Book> bookList) throws Exception {
		XmlSerializer xs=Xml.newSerializer();
		StringWriter sw=new StringWriter();
		//设置结果的输出对象是writer
		xs.setOutput(sw);
		xs.startDocument("utf-8", true);
		xs.startTag("", "books");
		for (Book book : bookList) {
			xs.startTag("", "book");
			xs.attribute("", "id", book.getBookId()+"");
			xs.startTag("", "name");
			xs.text(book.getBookName());
			xs.endTag("", "name");
			xs.startTag("", "price");
			xs.text(book.getBookPrice()+"");
			xs.endTag("", "price");
			xs.endTag("", "book");
		}
		xs.endTag("", "books");
		xs.endDocument();
		return sw.toString();
	}

}
package com.example.xmlanalysis;

import java.io.IOException;
import java.io.InputStream;
import java.util.Iterator;
import java.util.List;

import com.example.xmlanalysis.entity.Book;
import com.example.xmlanalysis.util.DOMUtil;
import com.example.xmlanalysis.util.PULLUtil;
import com.example.xmlanalysis.util.SAXUtil;

import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.Toast;

public class MainActivity extends Activity implements OnClickListener{
	private Button dom1,dom2,sax1,sax2,pull1,pull2;
	private InputStream is;
	private List<Book> bookList;
	private String str;
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		dom1=(Button) findViewById(R.id.main_dom_analysis);
		dom2=(Button) findViewById(R.id.main_dom_back_analysis);
		sax1=(Button) findViewById(R.id.main_sax_analysis);
		sax2=(Button) findViewById(R.id.main_sax_back_analysis);
		pull1=(Button) findViewById(R.id.main_pull_analysis);
		pull2=(Button) findViewById(R.id.main_pull_back_analysis);
		dom1.setOnClickListener(this);
		dom2.setOnClickListener(this);
		sax1.setOnClickListener(this);
		sax2.setOnClickListener(this);
		pull1.setOnClickListener(this);
		pull2.setOnClickListener(this);
		try {
			is=this.getAssets().open("book.xml");
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
	}


	@Override
	public void onClick(View v) {
		DOMUtil domUtil=new DOMUtil();
		SAXUtil saxUtil=new SAXUtil();
		PULLUtil pullUtil=new PULLUtil();
		switch (v.getId()) {
		case R.id.main_dom_analysis:
			try {
				bookList=domUtil.getBookList(is);
				String content="";
				for (Book b : bookList) {
					content+=b.toString();
				}
				Toast.makeText(MainActivity.this, "dom解析:"+content, Toast.LENGTH_SHORT).show();
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			break;
		case R.id.main_dom_back_analysis:
			try {
				String str=domUtil.setBookList(bookList);
				Toast.makeText(MainActivity.this, str, Toast.LENGTH_SHORT).show();
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			break;
		case R.id.main_sax_analysis:
			try {
				bookList=saxUtil.getBookList(is);
				String content="";
				for (Book book : bookList) {
					content+=book.toString();
				}
				Toast.makeText(MainActivity.this, content, Toast.LENGTH_SHORT).show();
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
			break;
		case R.id.main_sax_back_analysis:
			try {
				String str = saxUtil.setBookList(bookList);
				Toast.makeText(MainActivity.this, str, Toast.LENGTH_SHORT).show();
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			break;
		case R.id.main_pull_analysis:
			try {
				bookList=pullUtil.getBookList(is);
				String content="";
				for (Book book : bookList) {
					content+=book.toString();
				}
				Toast.makeText(MainActivity.this, content, Toast.LENGTH_SHORT).show();
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			break;
		case R.id.main_pull_back_analysis:
			try {
				String str = pullUtil.setBookList(bookList);
				Toast.makeText(MainActivity.this, str, Toast.LENGTH_SHORT).show();
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			break;
		default:
			break;
		}
	}
}
有个弊端,每次启动activity只能解析一次。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值