zoukankan      html  css  js  c++  java
  • android学习日记23--Android XML解析

    一、简述
      XML语言是跨平台,JAVA对XML语言支持得比较好,android系统的应用层平台是JAVA做的,所以用XML。
    XML解析比较简单。XML解析就是将获取到的数据分离出来,基本的网络数据传输,需要使用XML
    比如天气预报,从网上获取的是XML文件,通过XML解析可以把天气状态读出来
    例:

    1 <forecast_date data="2009-07-31" />
    2 <condition data="晴" />
    3 <humidity data="湿度: 65%" />(XML文件不全)

    可得到 2009-07-31 晴 湿度:65%

    还有一作用是保存你的数据,比如做个旅游网站,你需要把全国各个省、城市名称写到XML文件进行保存,在程序中通过解析读取调用。


    Android 平台上可用的XML解析有三种
    1、Simple API for XML(SAX)
    2、Document Object Model(DOM)
    3、Android附带的pull解析器

    二、实例
    分别用三种方法解析如下persons.xml文件(文件放在assert目录下)

     1 <?xml version="1.0" encoding="UTF-8"?>
     2 <persons>
     3     <person id="23">
     4         <name>liming</name>
     5         <age>30</age>
     6     </person>
     7     <person id="20">
     8         <name>dehua</name>
     9         <age>25</age>
    10     </person>
    11 </persons>

    还需定义个javabean 用于存放解析出来的内容

     1 package com.example.xml;
     2 
     3 public class Person {
     4     private Integer id;
     5     private String name;
     6     private Short age;
     7 
     8     public Integer getId() {
     9         return id;
    10     }
    11 
    12     public void setId(Integer id) {
    13         this.id = id;
    14     }
    15 
    16     public String getName() {
    17         return name;
    18     }
    19 
    20     public void setName(String name) {
    21         this.name = name;
    22     }
    23 
    24     public Short getAge() {
    25         return age;
    26     }
    27 
    28     public void setAge(Short age) {
    29         this.age = age;
    30     }
    31 
    32 //    @Override
    33 //    public String toString() {
    34 //        return "id:" + id + ", name:" + name + ", age:" + age;
    35 //    }
    36 }

    1、Simple API for XML(SAX)

      SAX是一个解析速度快并且占用内存少的XML解析器,很适合用于Android等移动设备。
    SAX解析XML文件采用的是事件驱动,也就是说,它并不需要解析完整个文档,在按内容顺序解析文档的过程中,
    SAX会判断当前读到的字符是否合法XML语法中的某部分,如果符合就会触发事件。所谓事件,其实就是一些回调(callback)方法,
    这些方法(事件)定义在ContentHandler接口。

      直接看代码:

     1 public class XMLContentHandler extends DefaultHandler {
     2     private List<Person> persons = null;
     3     private Person currentPerson;
     4     private String tagName = null;// 当前解析的元素标签    
     5     private static final String TAG = "XMLContentHandler"; 
     6 
     7     public List<Person> getPersons() {
     8         return persons;
     9     }
    10 
    11     /* 
    12      * 接收文档的开始的通知。
    13      */
    14 
    15     @Override
    16     public void startDocument() throws SAXException {
    17         persons = new ArrayList<Person>();
    18          Log.i(TAG, "startDocument");  
    19     }
    20     
    21     /* 
    22      * 结束文档的开始的通知。
    23      */
    24 
    25     @Override
    26     public void endDocument() throws SAXException {
    27         super.endDocument();
    28          Log.i(TAG, "endDocument");  
    29     }
    30 
    31     /* 
    32      * 接收字符数据的通知。
    33      */
    34 
    35     @Override
    36     public void characters(char[] ch, int start, int length)
    37             throws SAXException {
    38         if (tagName != null) {
    39             String data = new String(ch, start, length);
    40             if (tagName.equals("name")) {
    41                 this.currentPerson.setName(data);
    42             } else if (tagName.equals("age")) {
    43                 this.currentPerson.setAge(Short.parseShort(data));
    44             }
    45         }
    46         Log.i(TAG, "characters("+ch.toString()+","+start+","+length+")"); 
    47 
    48     }
    49 
    50     /*
    51      * 
    52      * 接收元素开始的通知。
    53      * 参数意义如下: 
    54      * namespaceURI:元素的命名空间 
    55      * localName :元素的本地名称(不带前缀) 
    56      * qName :元素的限定名(带前缀)
    57      * atts :元素的属性集合
    58      */
    59 
    60     @Override
    61     public void startElement(String namespaceURI, String localName,
    62             String qName, Attributes atts) throws SAXException {
    63 
    64         if (localName.equals("person")) {
    65             currentPerson = new Person();
    66             currentPerson.setId(Integer.parseInt(atts.getValue("id")));
    67         }
    68 
    69         this.tagName = localName;
    70         Log.i(TAG, "startElement("+namespaceURI+","+localName+","+qName+atts+")"); 
    71 
    72     }
    73 
    74     /* 
    75      * 接收文档的结尾的通知。
    76      * 参数意义如下:
    77      * uri :元素的命名空间
    78      * localName :元素的本地名称(不带前缀)
    79      * name :元素的限定名(带前缀)
    80      */
    81     @Override
    82     public void endElement(String uri, String localName, String name)
    83             throws SAXException {
    84 
    85         if (localName.equals("person")) {
    86             persons.add(currentPerson);
    87             currentPerson = null;
    88         }
    89 
    90         this.tagName = null;
    91         Log.i(TAG, "endElement("+uri+","+localName+","+name+")"); 
    92 
    93     }
    94 }


    2、Document Object Model(DOM)
      DOM解析XML文件时,会将XML文件的所有内容读取到内存中,然后允许您使用DOM API遍历XML树、检索所需的数据。
    使用DOM操作XML的代码看起来比较直观,并且,在某些方面比基于SAX的实现更加简单。但是,因为DOM需要将XML文件的所有内容读取到内存中,
    所以内存的消耗比较大,特别对于运行Android的移动设备来说,因为设备的资源比较宝贵,所以建议还是采用SAX来解析XML文件,
    当然,如果XML文件的内容比较小采用DOM是可行的。

     1 public class DomParseXML {
     2 
     3     public List<Person> readXML(InputStream inStream) {
     4 
     5         List<Person> persons = new ArrayList<Person>();
     6 
     7         DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();// 获取实例
     8 
     9         try {
    10 
    11             DocumentBuilder builder = factory.newDocumentBuilder();
    12             Document dom = builder.parse(inStream);
    13             Element root = dom.getDocumentElement();
    14             NodeList items = root.getElementsByTagName("person");// 查找所有person节点
    15 
    16             for (int i = 0; i < items.getLength(); i++) {
    17 
    18                 Person person = new Person();
    19 
    20                 // 得到第一个person节点
    21                 Element personNode = (Element) items.item(i);
    22 
    23                 // 获取person节点的id属性值
    24                 person.setId(new Integer(personNode.getAttribute("id")));
    25 
    26                 // 获取person节点下的所有子节点(标签之间的空白节点和name/age元素)
    27                 NodeList childsNodes = personNode.getChildNodes();
    28 
    29                 for (int j = 0; j < childsNodes.getLength(); j++) {
    30 
    31                     Node node = (Node) childsNodes.item(j); // 判断是否为元素类型
    32                     if (node.getNodeType() == Node.ELEMENT_NODE) {
    33                         Element childNode = (Element) node;
    34 
    35                         // 判断是否name元素
    36                         if ("name".equals(childNode.getNodeName())) {
    37 
    38                             // 获取name元素下Text节点,然后从Text节点获取数据
    39                             person.setName(childNode.getFirstChild()
    40                                     .getNodeValue());
    41 
    42                         } else if ("age".equals(childNode.getNodeName())) {
    43                             person.setAge(new Short(childNode.getFirstChild()
    44                                     .getNodeValue()));
    45 
    46                         }
    47                     }
    48                 }
    49                 persons.add(person);
    50             }
    51             inStream.close();
    52         } catch (Exception e) {
    53             e.printStackTrace();
    54         }
    55 
    56         return persons;
    57 
    58     }
    59 }

    3、Android附带的pull解析器
      Pull解析和Sax解析很相似,都是轻量级的解析,在Android的内核中已经嵌入了Pull,所以我们不需要再添加第三方jar包来支持Pull。
    Pull解析和Sax解析不一样的地方有(1)pull读取xml文件后触发相应的事件调用方法返回的是数字(2)pull可以在程序中控制想解析到哪里就可以停止解析。

     1 public class PullParseXML {
     2     
     3     public List<Person> readXML(InputStream inStream) throws XmlPullParserException, IOException{
     4 
     5         List<Person> persons = null;  
     6         Person person = null;  
     7         XmlPullParser parser = Xml.newPullParser();  
     8         parser.setInput(inStream, "UTF-8");  
     9           
    10         int event = parser.getEventType();//产生第一个事件  
    11         while(event!=XmlPullParser.END_DOCUMENT){  
    12             switch(event){  
    13             case XmlPullParser.START_DOCUMENT://判断当前事件是否是文档开始事件  
    14                 persons = new ArrayList<Person>();//初始化Persons集合  
    15                 break;  
    16             case XmlPullParser.START_TAG://判断当前事件是否是标签元素开始事件  
    17                 if("person".equals(parser.getName())){//判断开始标签元素是否是person  
    18                     person = new Person();  
    19                     person.setId(Integer.parseInt(parser.getAttributeValue(0)));//得到Person标签的属性值,并设置Person的id  
    20                 }  
    21                 if(person!=null){  
    22                     if("name".equals(parser.getName())){//判断开始标签元素是否是name  
    23                         person.setName(parser.nextText());  
    24                     }else if("age".equals(parser.getName())){//判断开始标签元素是否是price  
    25                         person.setAge(Short.parseShort(parser.nextText()));  
    26                     }  
    27                 }  
    28                 break;  
    29             case XmlPullParser.END_TAG://判断当前事件是否是标签元素结束事件  
    30                 if("person".equals(parser.getName())){//判断结束标签元素是否是Person  
    31                     persons.add(person);//将person添加到persons集合  
    32                     person = null;  
    33                 }  
    34                 break;  
    35             }  
    36             event = parser.next();//进入下一个元素并触发相应事件  
    37         }//end while  
    38         return persons;  
    39 
    40     }
    41 }

    运行界面:

    绑定按钮触发的事件代码:

     1 @Override
     2     protected void onCreate(Bundle savedInstanceState) {
     3         super.onCreate(savedInstanceState);
     4         setContentView(R.layout.activity_main);
     5         textView = (TextView)findViewById(R.id.textView);  
     6         sax_prase = (Button)findViewById(R.id.sax_prase);  
     7         dom_parse = (Button)findViewById(R.id.dom_parse);  
     8         pull_parse = (Button)findViewById(R.id.pull_parse);
     9         
    10         
    11         try {
    12             inStream = getAssets().open("persons.xml");
    13         } catch (IOException e) {
    14             // TODO Auto-generated catch block
    15             e.printStackTrace();
    16         }
    17         
    18         //绑定按钮监听器  
    19         sax_prase.setOnClickListener(new OnClickListener() {  
    20             @Override  
    21             public void onClick(View v) {  
    22                 persons = SaxParseXML(inStream); 
    23                 for (Person person : persons) {  
    24                     Log.i(TAG, person.getId()+":"+person.getName()+":"+person.getAge()); 
    25                 } 
    26             }  
    27         });  
    28         //绑定按钮监听器  
    29         dom_parse.setOnClickListener(new OnClickListener() {  
    30             @Override  
    31             public void onClick(View v) {  
    32                 
    33                 DomParseXML domParseXML = new DomParseXML();            
    34                 persons = domParseXML.readXML(inStream);
    35                 for (Person person : persons) {  
    36                     Log.i(TAG, person.getId()+":"+person.getName()+":"+person.getAge()); 
    37                 } 
    38             }  
    39         });  
    40         pull_parse.setOnClickListener(new OnClickListener() {  
    41             @Override  
    42             public void onClick(View v) {  
    43                 
    44                 PullParseXML pullParseXML = new PullParseXML();                             
    45                 try {
    46                     persons = pullParseXML.readXML(inStream);
    47                 } catch (XmlPullParserException e) {
    48                     // TODO Auto-generated catch block
    49                     e.printStackTrace();
    50                 } catch (IOException e) {
    51                     // TODO Auto-generated catch block
    52                     e.printStackTrace();
    53                 }
    54                 for (Person person : persons) {  
    55                     Log.i(TAG, person.getId()+":"+person.getName()+":"+person.getAge()); 
    56                 } 
    57                 
    58             }  
    59         });
    60     }
    61 
    62     private static List<Person> SaxParseXML(InputStream inStream) {
    63         // TODO Auto-generated method stub
    64         try {
    65             SAXParserFactory spf = SAXParserFactory.newInstance();
    66             SAXParser saxParser = spf.newSAXParser(); // 创建解析器
    67 
    68             // 设置解析器的相关特性,http://xml.org/sax/features/namespaces = true
    69             // 表示开启命名空间特性,缺省情况设为true,设置使代码更具可读性,但我加进去报错,索性注释掉
    70             //saxParser.setProperty("http://xml.org/sax/features/namespaces",true);
    71             XMLContentHandler handler = new XMLContentHandler();
    72                         
    73             saxParser.parse(inStream, handler);
    74             inStream.close();
    75 
    76             return handler.getPersons();
    77 
    78         } catch (Exception e) {
    79 
    80             e.printStackTrace();
    81 
    82         }
    83 
    84         return null;
    85     }

    分别点击三个按钮用不同方法解析出来的结果:


    三、总结
      对于三种解析XML方法,各有千秋,倾向于PULL解析器,因为SAX解析器操作起来太笨重,DOM不适合文档较大,内存较小的场景,
    唯有Pull轻巧灵活,速度快,占用内存小,使用非常顺手,Pull解析可以用于很多场合,例如接受google天气,rss新闻等。

  • 相关阅读:
    Nginx禁止IP,只允许指定域名访问
    预防vsphere勒索病毒,适用于 ESXi 6.x 中的 OpenSLP 安全漏洞 (CVE-2019-5544) 的权宜措施 (76372)
    解决 vCenter root 密码过期无法登陆 User password expired
    停用Veritas Smart Meter-概念与操作
    centos7.0 没有netstat 和 ifconfig命令问题
    MAVEN剪除传递依赖
    Spring+SpringMVC+MyBatis+Maven框架整合
    CentOS7配置MongoDB
    利用mybatis-generator自动生成代码
    idea提交本地项目到git
  • 原文地址:https://www.cnblogs.com/aiguozhe/p/3632365.html
Copyright © 2011-2022 走看看