XML解析的三种方式总结

来源:互联网 发布:dota牛蛙淘宝店 编辑:程序博客网 时间:2024/05/16 09:08

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

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

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

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

主要的方法有

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

这个方法是在开始解析文档的时候调用,通常做一下初始化的工作,然后就绪执行startElement()方法

@Overridepublic void startElement(String uri, String localName, String qName,Attributes attributes) throws SAXException {......preTag = localName; }

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

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

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

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

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

接着会调用endElement()方法

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

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

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

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

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

@Overridepublic 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();




0 0
原创粉丝点击