Xml解析之——Java/Android/Python
一、Xml文件 test.xml
1
2 George
3 John
4 Reminder
5
Don't forget the meeting!
6
7 fetch="."
8 review="gerrit.huaqin.com:8081" />
9
10 remote="origin"
11 sync-j="4" />
12
上面是一个简单的xml文件,个人的理解:xml文件是一个格式标准,代码清晰的树形结构体。
二、Xml文件的解析
xml解析主要是有SAX和DOM ,python还另外提供了ElementTree(轻量级的DOM),android提供了PULL。
简单的介绍下集中解析方式
DOM:将整个XML文件解析到内存生成一个树形结构。
优点:整个文档树在内存中,便于操作;支持删除、修改、重新排列等多种功能;缺点:将整个文档调入内存(包括无用的节点),浪费时间和空间;
适用点:对象传输,全文件的数据修改等
SAX:基于事件驱动的,也就是说解析器去从xml文件的开始往下走,当发现元素开始、元素结束、文本、文档的开始或结束等时,发送事件,程序员编写响应这些事件的代码,保存数据。
优点:不用事先调入整个文档,占用资源少
适用点:元素检索
PULL:运行方式和SAX类似,基于事件的模式。不同的是,在PULL解析过程中,我们需要自己获取产生的事件然后做相应的操作,而不像SAX那样由处理器触发一种事件的方法,执行我们的代码。PULL解析器小巧轻便,解析速度快,简单易用,非常适合在Android移动设备中使用,Android系统内部在解析各种XML时也是用PULL解析器。
三、例子
我们就以操作test.xml为例。
1.DOM(python实现)
1 __author__ = 'xuqiang'
2 from xml.dom importminidom,Node3
4 #先将文件解析出来放在DOMTree中
5 DOMTree = minidom.parse("test.xml")6 #取根节点
7 note =DOMTree.documentElement8 length =len(note.childNodes)9 #依次取子节点
10 for child innote.childNodes:11 if child.nodeType ==Node.COMMENT_NODE:12 print child.name + ':' +child.nodeValue13 elif child.nodeType ==Node.ELEMENT_NODE:14 print "" %child.nodeName15 #取子就子节点属性
16 ifchild.hasAttributes():17 attributes =child.attributes18 for index inrange(attributes.length):19 print "%s = %s" %(attributes.item(index).name,attributes.item(index).value)20 #去子节点的文本
21 ifchild.hasChildNodes():22 print "%s" %child.childNodes[0].data23 print "%s>" % child.nodeName
2.SAX
SAX最佳使用的地方就是查找某个元素的值
假设我们要取test.xml中字节点remote的属性name的值
1 __author__ = 'xuqiang'
2
3 importxml4 importxml.sax5
6 classTestHandler(xml.sax.ContentHandler):7 def __init__(self):8 self.to = ""
9 self.fromm = ""
10 self.heading = ""
11 self.body = ""
12 self.review = ""
13 self.name = ""
14 self.fetch = ""
15 self.remote = ""
16 self.defaultremote = ""
17 self.sync = ""
18 self.revision = ""
19 self.default = ""
20
21 defstartElement(self, tag, attributes):22 self.CurrentData =tag23 #找到节点remote的属性 name
24 if tag == 'remote':25 print "remote name is %s" % attributes.get('name')26
27 defendElement(self, tag):28 if self.CurrentData == "to":29 print "to:", self.to30 elif self.CurrentData == "from":31 print "from:", self.fromm32 elif self.CurrentData == "heading":33 print "heading:", self.heading34 elif self.CurrentData == "body":35 print "body:", self.body36 elif self.CurrentData == "remote":37 print "remote:", self.remote38 elif self.CurrentData == "default":39 print "default:", self.default40 self.CurrentData = ""
41
42 defcharacters(self, content):43 if self.CurrentData == "to":44 self.to =content45 elif self.CurrentData == "from":46 self.fromm =content47 elif self.CurrentData == "heading":48 self.heading =content49 elif self.CurrentData == "body":50 self.body =content51 elif self.CurrentData == "remote":52 self.remote =content53 elif self.CurrentData == "default":54 self.default =content55
56 parser =xml.sax.make_parser()57 parser.setFeature(xml.sax.handler.feature_namespaces, 0)58 Handler =TestHandler()59 parser.setContentHandler(Handler)60 parser.parse("test.xml")
DOM和SAX是最常见的解写xml的方式,这里python实现,java的实现基本差别不大
三、PULL
PULL是android中最常用的解析xml的方式。他的原理和SAX类似,是基于事件处理的。使用方法也类似。
我们以谷歌天气为例,这是我们从google官方网站上下载下来的xml格式的当天天气。
1 <?xml version="1.0" encoding="utf-8"?>
2
3
4
5 CN
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
xml文件中参数比较多,我现在只想知道城市,温度,适度,风向四个值,建立一个数据结构CurrentWeatherXml来保存这四个值
1 packageorg.xerrard.xmlpulldemo;2
3 public classCurrentWeatherXml {4
5
6 public String city; //城市
7 public String temperature; //温度
8 public String humidity; //湿度
9 public String wind_direction; //风向
10
11 publicString toString()12 {13 //摄氏度(℃)=K-273。
14 float s =Float.parseFloat(temperature);15 float temperatureC = s-273;16
17 StringBuilder sb = newStringBuilder();18 sb.append(" 城市: ").append(city);19 sb.append(" 天气: ").append(temperature + "").append(" °K");20 sb.append(" 天气: ").append(temperatureC + "").append(" °C");21 sb.append(" 湿度 ").append(humidity);22 sb.append(" 风向 ").append(wind_direction);23 returnsb.toString();24 }25 }
我们建立一个Model类来做xml的处理,在这个类中,我们对xml文件进行解析,从中抽取城市,天气,湿度,风向,并将其值存入到CurrentWeatherXml中
1 packageorg.xerrard.xmlpulldemo;2
3 importjava.io.InputStream;4
5 importorg.xmlpull.v1.XmlPullParser;6 importorg.xmlpull.v1.XmlPullParserFactory;7
8 importandroid.util.Log;9
10 public classWeatherXMLModel {11
12 public static CurrentWeatherXml curCondition = null;13
14 public static voidinitData(InputStream is){15 try{16 if(is != null){17 XmlPullParserFactory factory =XmlPullParserFactory.newInstance();18 XmlPullParser parser =factory.newPullParser();19 parser.setInput(is, "UTF-8");20 int eventType =parser.getEventType();21 while(eventType !=XmlPullParser.END_DOCUMENT){22 switch(eventType) {23 caseXmlPullParser.START_DOCUMENT:24 Log.d("xerrard", "START_DOCUMENT=" +parser.getName());25 break;26 caseXmlPullParser.START_TAG:27 String name =parser.getName();28
29 if("current".equals(name)){//current标签
30 Log.d("xerrard", "START_TAG=" +name);31 curCondition = newCurrentWeatherXml();32 }else if(curCondition != null){33 if("city".equals(name)){ //city标签
34 curCondition.city = parser.getAttributeValue(1);35 }36 if("temperature".equals(name)){ //temperature标签
37 curCondition.temperature = parser.getAttributeValue(0);38 }39 if("humidity".equals(name)){ //humidity标签
40 curCondition.humidity = parser.getAttributeValue(0);41 }42 if("direction".equals(name)){ //direction标签
43 curCondition.wind_direction = parser.getAttributeValue(0);44 }45 }46
47
48 break;49
50 caseXmlPullParser.END_TAG:51 if("forecast_conditions".equals(parser.getName())){52 Log.d("xerrard", "END_TAG=" +parser.getName());53 }54 break;55 }56 eventType =parser.next();57 }58 Log.d("xerrard", "curCondition--" +curCondition);59 }60 } catch(Exception e) {61 e.printStackTrace();62 }63 }64
65 }
然后,我们就可以将xml文件作为参数传递给WeatherXmlModel,WeatherXmlModer处理完毕后,得到我们需要的数据CurrentWeatherXml。
1 InputStream inputStream = newFileInputStream(xmlFlie);2 WeatherXMLModel.initData(inputStream);3 CurrentWeatherXml weather =WeatherXMLModel.curCondition;4 TextView hello =(TextView)findViewById(R.id.hello);5 hello.setText(weather.toString());