XML序列化及PULL解析,DOM解析,SAX解析

需要解析或者序列化的XML文件如下:

<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
<Persons>
	<Person Id="0"> Hello World
		<Age>20</Age>
		<Name>zhang0</Name>
	</Person>
	
	<Person Id="1">Hello World
		<Age>21</Age>
		<Name>zhang1</Name>
	</Person>
	
	<Person Id="2">Hello World
		<Age>22</Age>
		<Name>zhang2</Name>
	</Person>
	
	<Person Id="3">Hello World
		<Age>23</Age>
		<Name>zhang3</Name>
	</Person>
	
	<Person Id="4">Hello World
		<Age>24</Age>
		<Name>zhang4</Name>
	</Person>
</Persons>

一、XML序列化

/**
	 * 往/data/data/包名/files/person.xml里生成XML数据
	 * @param personList
	 * @return true 序列化成功    false 序列化失败
	 */
	private boolean mXMLSerializer(List<Person> personList){
		try {
			//获取XML序列化对象
			XmlSerializer serializer = Xml.newSerializer();
			//文件流对象
			FileOutputStream fos = openFileOutput("person.xml", Context.MODE_PRIVATE);
			//序列化对象往文件流里写数据
			serializer.setOutput(fos, "utf-8");
			//开始序列化,对应于<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
			serializer.startDocument("utf-8", true);
			//开始标签,对应于<Persons>
			serializer.startTag(null, "Persons");
			for(int i=0; i<personList.size(); i++){
				serializer.startTag(null, "Person");
				serializer.attribute(null, "Id", String.valueOf(personList.get(i).getId()));
				serializer.text("Hello World");
				serializer.startTag(null, "Age");
				serializer.text(String.valueOf(personList.get(i).getAge()));
				serializer.endTag(null, "Age");
				serializer.startTag(null, "Name");
				serializer.text(personList.get(i).getName());
				serializer.endTag(null, "Name");
				serializer.endTag(null, "Person");
			}
			serializer.endTag(null, "Persons");
			serializer.endDocument();
			return true;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return false;
	}

二、XML解析

1、Pull解析:

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

private List<Person> mXMLPullParse(){
		try {
			//获取PULL解析器对象
			XmlPullParser parser = Xml.newPullParser();
			//文件输入流
			FileInputStream fis = openFileInput("person.xml");
			//把解析器和文件输入流绑定
			parser.setInput(fis, "utf-8");
			//解析器的事件
			int eventType = parser.getEventType();
			List<Person> personList =  null;
			String name = null;
			Person person = null;
			//只要读到的事件不是文件的结束,就继续循环
			while(eventType != XmlPullParser.END_DOCUMENT){
				name = parser.getName();
				switch (eventType) {
				//开始标签,类似于<Persons> <Person> <Age>之类的
				case XmlPullParser.START_TAG:
					if("Persons".equals(name)){
						personList = new ArrayList<Person>();
					} else if("Person".equals(name)){
						person = new Person() ;
						//获得该标签的属性
						String id = parser.getAttributeValue(null, "Id");
						person.setId(Integer.parseInt(id));
					} else if("Age".equals(name)){
						//获得该标签里的值 <Age>19</Age> 即19
						String age = parser.nextText();
						person.setAge(Integer.parseInt(age));
					} else if("Name".equals(name)){
						person.setName(parser.nextText());
					}
					break;
				case XmlPullParser.END_TAG:
					if("Person".equals(name)){
						personList.add(person);
					} else if("Persons".equals(name)){
						return personList;
					}
					break;
				case XmlPullParser.TEXT:
					//对应于 Hello World
					Log.i("XmlPullParser", parser.getText());
					break;
				default:
					break;
				}
				//使解析事件往下走
				eventType = parser.next();
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

2、DOM解析

DOM是基于树形结构的的节点或信息片段的集合,允许开发人员使用DOM API遍历XML树、检索所需数据。分析该结构通常需要加载整个文档和构造树形结构,然后才可以检索和更新节点信息。

由于DOM在内存中以树形结构存放,因此检索和更新效率会更高。但是对于特别大的文档,解析和加载整个文档将会很耗资源,所以Android中使用此方式解析XML并不常见。


/**
	 * DOM解析XML
	 * @param is 输入流
	 * @return 异常返回null
	 */
	public static List<Person> mParse(InputStream is) {
		try {
			// 获得DOM解析工厂对象
			DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
			// 获得DOM对象
			DocumentBuilder builder = dbf.newDocumentBuilder();
			// 解析输入流,得到文档对象
			Document document = builder.parse(is);
			// 获得文档对象的根元素
			Element root = document.getDocumentElement();
			// 由根元素对象获得标签名字为Peson的一个集合
			NodeList childNodes = root.getElementsByTagName("Person");
			Person person = null;
			List<Person> personList = new ArrayList<Person>();
			// 遍历该集合
			for (int i = 0; i < childNodes.getLength(); i++) {
				person = new Person();
				// 获得子节点,强转为元素。假如i=0,那么就是第一个<Person></Person>这样的节点。
				Element item = (Element) childNodes.item(i);
				// 获得<Person Id="5">这里的"5"
				person.setId(Integer.parseInt(item.getAttribute("Id")));
				// 再次获取<Person>节点里的子节点集合
				NodeList childNodes2 = item.getChildNodes();
				for (int j = 0; j < childNodes2.getLength(); j++) {
					// 获取子节点里每个节点。
					Node item2 = childNodes2.item(j);
					// 判断是否为元素节点。
					// <Person>
					// Hello World :第一个子节点
					// <Age></Age> :第二个子节点
					// </Person>
					// 像上面的这个例子中,Person节点里就有两个子节点,一个是Hello一个是<Age></Age>,只有Age才是元素节点
					if (item2.getNodeType() == Node.ELEMENT_NODE) {
						Element e = (Element) item2;
						if ("Age".equals(e.getNodeName())) {
							// e.getFirstChild().getNodeValue(),如果是上面的这个例子,会获取Hello这个内容。
							person.setAge(Integer.parseInt(e.getFirstChild()
									.getNodeValue()));
						} else if ("Name".equals(e.getNodeName())) {
							person.setName(e.getFirstChild().getNodeValue());
						}
					}
				}
				personList.add(person);
			}
			return personList;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}


3、SAX解析

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

(1)定义一个类,继承与DefaultHandler类,代码如下:

public class SAXHandler extends DefaultHandler {
	private String content;
	private List<Person> personList;
	private Person person;
	
	//获取解析的内容
	public List<Person> getPersonList(){
		return personList;
	}
	
	@Override
	public void characters(char[] ch, int start, int length)
			throws SAXException {
		super.characters(ch, start, length);
		//获取对应的解析值
		content = new String(ch, start, length);
	}

	@Override
	public void endDocument() throws SAXException {
		super.endDocument();
		Log.i("endDocument", "--------endDocument---------");
	}

	@Override
	public void endElement(String uri, String localName, String qName)
			throws SAXException {
		super.endElement(uri, localName, qName);
		if("Age".equals(localName)){
			person.setAge(Integer.parseInt(content));
		} else if("Name".equals(localName)){
			person.setName(content);
		} else if("Person".equals(localName)){
			personList.add(person);
		}
	}

	@Override
	public void startDocument() throws SAXException {
		super.startDocument();
		Log.i("startDocument", "-------startDocument---------");
		personList = new ArrayList<Person>();
	}

	@Override
	public void startElement(String uri, String localName, String qName,
			Attributes attributes) throws SAXException {
		super.startElement(uri, localName, qName, attributes);
		if("Person".equals(localName)){
			person = new Person();
			person.setId(Integer.parseInt(attributes.getValue("Id")));
		}
	}
	
}

(2)SAX解析类

/**
	 * SAX解析XML
	 * @param is 输入流
	 * @return 异常返回null
	 */
	public static List<Person> mParse(InputStream is) {
		try {
			//获得SAX解析工厂对象
			SAXParserFactory factory = SAXParserFactory.newInstance();
			//获得SAX解析对象
			SAXParser saxParser = factory.newSAXParser();
			SAXHandler saxHandler = new SAXHandler();
			//SAX解析,参数为输入流和DefaultHandler的子类
			saxParser.parse(is, saxHandler);
			List<Person> personList = saxHandler.getPersonList();
			return personList;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值