zoukankan      html  css  js  c++  java
  • 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天气

  • 相关阅读:
    PHP扩展开发报错解决[error: ‘PHP_FE_END’ undeclared here (not in a function)] .
    php 如何获取一个变量的名字
    php 使用异或(XOR)加密/解密文件
    php 常用自定义方法
    使用onbeforeunload事件检测窗口是否刷新或关闭
    mysql 优化 insert 性能
    《高级软件测试》11.28.全员配置环境并学习测试环境的使用
    《高级软件测试》11.27.小组开会
    《高级软件测试》11.25.黑盒测试实践作业及任务划分
    第一周小组博客作业
  • 原文地址:https://www.cnblogs.com/xerrard/p/5022715.html
Copyright © 2011-2022 走看看