Xml解析之——Java/Android/Python
Xml解析之——Java/Android/Python
一、Xml文件 test.xml
1 <note> 2 <to>George</to> 3 <from>John</from> 4 <heading>Reminder</heading> 5 <body>Don't forget the meeting!</body> 6 <remote name="origin" 7 fetch="." 8 review="gerrit.huaqin.com:8081" /> 9 <default revision="pythontest" 10 remote="origin" 11 sync-j="4" /> 12 </note>
上面是一个简单的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 import minidom,Node 3 4 #先将文件解析出来放在DOMTree中 5 DOMTree = minidom.parse("test.xml") 6 #取根节点 7 note = DOMTree.documentElement 8 length = len(note.childNodes) 9 #依次取子节点 10 for child in note.childNodes: 11 if child.nodeType == Node.COMMENT_NODE: 12 print child.name + ':' + child.nodeValue 13 elif child.nodeType == Node.ELEMENT_NODE: 14 print "<%s>" % child.nodeName 15 #取子就子节点属性 16 if child.hasAttributes(): 17 attributes = child.attributes 18 for index in range(attributes.length): 19 print " %s = %s" % (attributes.item(index).name,attributes.item(index).value) 20 #去子节点的文本 21 if child.hasChildNodes(): 22 print "%s" % child.childNodes[0].data 23 print "</%s>" % child.nodeName
2.SAX
SAX最佳使用的地方就是查找某个元素的值
假设我们要取test.xml中字节点remote的属性name的值
1 __author__ = 'xuqiang' 2 3 import xml 4 import xml.sax 5 6 class TestHandler(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 def startElement(self, tag, attributes): 22 self.CurrentData = tag 23 #找到节点remote的属性 name 24 if tag == 'remote': 25 print "remote name is %s" % attributes.get('name') 26 27 def endElement(self, tag): 28 if self.CurrentData == "to": 29 print "to:", self.to 30 elif self.CurrentData == "from": 31 print "from:", self.fromm 32 elif self.CurrentData == "heading": 33 print "heading:", self.heading 34 elif self.CurrentData == "body": 35 print "body:", self.body 36 elif self.CurrentData == "remote": 37 print "remote:", self.remote 38 elif self.CurrentData == "default": 39 print "default:", self.default 40 self.CurrentData = "" 41 42 def characters(self, content): 43 if self.CurrentData == "to": 44 self.to = content 45 elif self.CurrentData == "from": 46 self.fromm = content 47 elif self.CurrentData == "heading": 48 self.heading = content 49 elif self.CurrentData == "body": 50 self.body = content 51 elif self.CurrentData == "remote": 52 self.remote = content 53 elif self.CurrentData == "default": 54 self.default = content 55 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 <current> 3 <city id="1796236" name="Shanghai"> 4 <coord lon="121.46" lat="31.22"/> 5 <country>CN</country> 6 <sun rise="2015-12-13T22:44:16" set="2015-12-14T08:52:49"/> 7 </city> 8 <temperature value="283.15" min="283.15" max="283.15" unit="kelvin"/> 9 <humidity value="82" unit="%"/> 10 <pressure value="1024" unit="hPa"/> 11 <wind> 12 <speed value="5" name="Gentle Breeze"/> 13 <direction value="310" code="NW" name="Northwest"/> 14 </wind> 15 <clouds value="44" name="scattered clouds"/> 16 <visibility value="5000"/> 17 <precipitation mode="no"/> 18 <weather number="721" value="haze" icon="50d"/> 19 <lastupdate value="2015-12-14T03:00:00"/> 20 </current>
xml文件中参数比较多,我现在只想知道城市,温度,适度,风向四个值,建立一个数据结构CurrentWeatherXml来保存这四个值
1 package org.xerrard.xmlpulldemo; 2 3 public class CurrentWeatherXml { 4 5 6 public String city; //城市 7 public String temperature; // 温度 8 public String humidity; // 湿度 9 public String wind_direction; // 风向 10 11 public String toString() 12 { 13 //摄氏度(℃)=K-273。 14 float s = Float.parseFloat(temperature); 15 float temperatureC = s-273; 16 17 StringBuilder sb = new StringBuilder(); 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 return sb.toString(); 24 } 25 }
我们建立一个Model类来做xml的处理,在这个类中,我们对xml文件进行解析,从中抽取城市,天气,湿度,风向,并将其值存入到CurrentWeatherXml中
1 package org.xerrard.xmlpulldemo; 2 3 import java.io.InputStream; 4 5 import org.xmlpull.v1.XmlPullParser; 6 import org.xmlpull.v1.XmlPullParserFactory; 7 8 import android.util.Log; 9 10 public class WeatherXMLModel { 11 12 public static CurrentWeatherXml curCondition = null; 13 14 public static void initData(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 case XmlPullParser.START_DOCUMENT: 24 Log.d("xerrard", "START_DOCUMENT=" + parser.getName()); 25 break; 26 case XmlPullParser.START_TAG: 27 String name = parser.getName(); 28 29 if("current".equals(name)){//current标签 30 Log.d("xerrard", "START_TAG=" + name); 31 curCondition = new CurrentWeatherXml(); 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 case XmlPullParser.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 = new FileInputStream(xmlFlie); 2 WeatherXMLModel.initData(inputStream); 3 CurrentWeatherXml weather = WeatherXMLModel.curCondition; 4 TextView hello = (TextView)findViewById(R.id.hello); 5 hello.setText(weather.toString());
参考资料:
googleweatherapi : http://openweathermap.org/current
http://blog.csdn.net/jdsjlzx/article/details/7215289 PULL解析google天气