XML解析的三种方式总结

前端之家收集整理的这篇文章主要介绍了XML解析的三种方式总结前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

XML解析有三种方式,这里来总结一下

*************************SAX*************************

首先是SAX方式,这种方式是边加载边解析

关键的一个类是DefaultHandler,我们通过集成这个类,Override一些关键的方法,从而解析XML文件

主要的方法

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

这个方法是在开始解析文档的时候调用,通常做一下初始化的工作,然后就绪执行startElement()方法
@Override
	public void startElement(String uri,String localName,String qName,Attributes attributes) throws SAXException {
......
preTag = localName;
}

我在startElement()方法里面解析XML标签,其中localName是当前标签的名字,attributes是存储了标签属性的数组,我们通过if语句判断是否我们需要的标签,然后提取需要的属性信息来构造Bean就可以了

这里我们使用一个preTag全局变量来存储当前标签,便于character方法的使用

然后会接着执行character()方法,我们在这个方法里面提取文本信息

@Override
	public void characters(char[] ch,int start,int length)
			throws SAXException {		
		String content = new String(ch,start,length);
.......
}

这里构造出的content就是文本信息了,但是我怎么知道,这个那个标签里面的文本信息,这时就要使用到preTag,来判断是那个标签

接着会调用endElement()方法

@Override
	public void endElement(String uri,String qName)
			throws SAXException {	
		.......
		Log.i(tag,localName+"***end element***");
		preTag = null;
	}

这里我们有获得了localName,也就是当前标签的名字

并且我们有一个关键的操作,就是preTag=null的设置

因为xml文件里面,空白区域也被当成了节点,所以我们如果不设置pretag为空,那么preTag记录的就是上一个标签的名字,当我们解析到空白节点时,进入character()方法,就可能把远的preTag所对应的文本覆盖成空

最后调用endDocument()方法,做一些收尾的工作

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

继承好DefaultHandler类以后,我就要使用
InputStream is = PersonServiceTest.class.getClassLoader().getResourceAsStream("person.xml");
		if(is!=null){
			SAXForHandler s = new SAXForHandler();
			SAXParserFactory pf = SAXParserFactory.newInstance();
			SAXParser sp = pf.newSAXParser();
			sp.parse(is,s);
			for(Person person:s.list){
				Log.i(Tag,person.toString());
			}
		}

使用方法很简单,首先创建一个SAX工程,然后利用工程生成一个解析器

把xml数据流,和Handler对象传入解析器就可以了


*************************DOM*************************

dom解析方式是先加载整个xml文件再解析,这样的好处是,我们知道了DOM树的结构,和节点之间的关系,不利之处是要加载整个文件,解析速度慢

解析方式如下,首先创建一个DOMbulider工程,然后生产一个DOMbulider,把xml数据流传入DOMbulider.parse(),就可以生成一个DOMCUMENT对象

DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
		DocumentBuilder builder = factory.newDocumentBuilder();
		Document document = builder.parse(inStream);

下面的解析过程就比较难说清楚了,首先是获取文件根节点
Element root = document.getDocumentElement();

然后根据文件根节点,获取所有Node
NodeList personNodes = root.getElementsByTagName("person");

这里要说明一下node跟Elment,我们主要使用element来获取标签的相关信息,不过首先我们要使用Node转换成Element

我们通过一个循环,来遍历所有的Person,用node.item()来获取,对于每一个node,我们在强制转换成Element

for(int i=0;i<personNodes.getLength();i++){
			Element personElement = (Element) personNodes.item(i);
.....
}

有了element对象,我就可以获取它的属性
int id = new Integer(personElement.getAttribute("id"));

接着像根节点一样,获取该element的所有子节点
NodeList childNodes = personElement.getChildNodes();
			for(int y=0;y<childNodes.getLength();y++){
.....
}
不断地按照这个方式,就能完整构造出bean对象


*************************PULL*************************

PULL方法,可以说结合了上面两种方法解析便利上的优点,并且它表示通过工厂创建的,而是直接创建,但是接下来把xml流传进去解析,也是一样的步骤

XmlPullParser pullParser = Xml.newPullParser();
		pullParser.setInput(inStream,"UTF-8");

下面的解析全都围绕着pullParser这个对象进行了

首先一个方法是getEventType()获取当前节点的类型,注意每次pullParser都表示当前正在解析的节点,只有调用它的next()方法,才会移到下一个节点,类似cursor

判断节点类型后,不是END_DOCUEMNT,我们就一直解析(next())

接着几个属性就是XmlPullParser.START_DOCUMENT,XmlPullParser.START_TAG,XmlPullParser.END_TAG

根据不同类型解析就可以了

pullParser.getName()获得标签名字

pullParser.getAttributeValue(0)获得标签属性

pullParser.nextText()获得标签文本

调用上面的几个方法,勾构造bean就可以了

                int event = pullParser.getEventType();
		while(event!=XmlPullParser.END_DOCUMENT){
			switch(event){
			case XmlPullParser.START_DOCUMENT:
				persons = new ArrayList<Person>();
				break;
			case XmlPullParser.START_TAG:
				if("person".equals(pullParser.getName())){
					int id = new Integer(pullParser.getAttributeValue(0));
					person = new Person();
					person.setId(id);
				}
				if(person!=null){
					if("name".equals(pullParser.getName())){
						person.setName(pullParser.getAttributeValue(0));						
					}
					if("age".equals(pullParser.getName())){
						person.setAge(new Short(pullParser.nextText()));
					}
					if("ddd".equals(pullParser.getName())){						
						person.setDdd(pullParser.nextText());
					}
				}
				break;
			case XmlPullParser.END_TAG:
				if("person".equals(pullParser.getName())){
					persons.add(person);
					person = null;
				}
			}
			event = pullParser.next();
		}


说过XML的解析,我顺便说一下xml文件的构造,这种构造方法,跟pull解析的方式很类似,就是刚好反过来

首先获取一个序列化构造对象,设置输出

然后startDocument()方法,就可以开始构造文件根节点

然后startTag()就可以设置一个标签

attribute()就设置这个标签属性

text()就可以设置文本

endTag()就可以闭合标签

其中startTag相互嵌套,就可以构成树状结构

最好endDocument()就可以关闭root了

XmlSerializer serializer = Xml.newSerializer();
		serializer.setOutput(outStream,"UTF-8");
		serializer.startDocument("UTF-8",true);
		serializer.startTag(null,"persons");
		for (Person person : persons) {
			serializer.startTag(null,"person");
			serializer.attribute(null,"id","1");
			serializer.startTag(null,"name");
			serializer.text("zhangsan");
			serializer.endTag(null,"name");
		}
		serializer.endTag(null,"persons");
		serializer.endDocument();
		outStream.flush();
		outStream.close();

猜你在找的XML相关文章