`

转载!!!XML解析!

阅读更多
   悲剧!把一个初中同学给忘了,今天还和我聊天来着,尴尬的要命!!哎!

   好的,今天这个是XML解析。在android中应用非常的广泛的说。无论是从服务器获取数据还是从自己写好的xml中解析(不过在自己写好的xml中解析然后在读取确实没什么必要)。主要还是从服务器获取数据然后在前台显示以便用户很好的使用啊。

  今天的这个文章依然转自EOE。感谢敏感词依然给了留下了可以转载的权利!主要的还是感谢楼主,写了这么好的文章可以让我等瞻仰!虽然我自己也会写,但是绝对总结的没有如此的流畅和经典。

相信各位android开发者,对SAX已经并不陌生了,SAX(Simple API for XML),是一个使用非常广泛的XML解析标准,通常使用Handler模式来处理XML文档,这种处理模式和我们平常习惯的理解方式很不同,身边也经常有一些朋友在刚接触SAX的时候会觉得理解起来有些困难。其实SAX并不复杂,只不过是换了一种思维方式,正如它的名字所表示的,为了让我们以更简单的方式来处理XML文档,下面我们就开始吧。
      我们通常的理解方式是,我们给出一个输入(比如xml文档的地址),然后程序返回给我们数据(比如解析后的xml文档结构),我们在返回给我们的结果中进行相应的操作,而SAX以一种更简单的方式来处理XML文档的解析,也就是处理器模式,一个使用SAX的简单示例:

SAXParserFactory spf = SAXParserFactory.newInstance();
SAXParser sp = spf.newSAXParser();
XMLReader reader = sp.getXMLReader();


reader.setContentHandler(myHandler);           
reader.parse(new InputSource(new URL(url).openStream()));


正如上面的代码,我们使用一系列工厂方法生成了一个XMLReader对象,随后,最关键的一行就是reader.setContentHandler,这里为这个reader设置了一个处理器,这个处理器的具体内容是要我们来完成的,稍后会详细介绍,最后调用parse方法完成文档的解析。这是SAX的一个基本流程。
     下面我们来详细介绍一下处理器,SAX处理器使用的是一种和我们平时的理解方式不太一样的处理形式,是在遍历文档的同时,让我们来进行文档的处理。     用一个实际的例子来解释更为方便,假如有下面这样一个XML文档:

<student>
    <name>张三</name>
    <age>22</age>
    <sn>1001</sn>
   </student>
  <student>
    <name>李四</name>
    <age>21</age>
    <sn>1002</sn>
  </student>

使用SAX的时候,解析器会对XML文档进行深度优先遍历,在遍历的时候,会根据条件调用处理器中的方法,如上面的XML文档,首先会遍历到第一个student的起始节点,这时我们可以在处理器中进行一些需要的处理,随后会分别遍历name,age,sn起始节点和结束节点,以此类推,这样说起来可能还不够直观,下面我们就来看看一个处理器的基本结构:

public class MyHandler extends DefaultHandler {
    
     public void startElement(String uri, String localName, String qName,   
     }
    
     public void endElement(String uri, String localName, String qName)
             throws SAXException {   
     }
    
     public void characters(char[] ch, int start, int length)
             throws SAXException {


     } 
}


如上面的代码,这里有几个比较重要的方法,startElement是进入到起始节点的时候会调用的方法,例如上面的xml文件,进入到<student>节点时,就会调用startElement方法。     endElement方法,在结束一个节点的时候会调用,例如进入到</student>节点时,该方法会被调用。     characters方法,在进入XML节点的文本节点(TextNode)时会被调用,例如<name>张三</name>,在便利到‘张三’这个文本节点的时候,这个方法会被调用。
     另外还有两个回调方法,分别为startDocument,endDocument,顾名思义,这两个方法为进入文档和离开文档时要调用的方法。

     下面我们就来自己写一个处理器来解析上面的XML文档。首先我们需要将每个节点封装成一个实体对象:

public class Student {
     private String name;
    
     private int age;
    
     private String sn;
     public String getName() {
         return name;
     }
     public void setName(String name) {
         this.name = name;
     }
     public int getAge() {
         return age;
     }
     public void setAge(int age) {
         this.age = age;
     }
     public String getSn() {
         return sn;
     }
     public void setSn(String sn) {
         this.sn = sn;
     }
    
    
}
 
下面再来完成处理器的代码:

public class MyHandler extends DefaultHandler {
    
     private List<Student> studentList;
    
     private boolean inStudent = false;
    
     private boolean studentName = false;
    
     private boolean studentAge = false;
    
     private boolean studentSN = false;
    
     private Student curStudent ;
    
     public MyHandler() {
        
         studentList = new ArrayList<Student>();
     }
     @Override
     public void startElement(String uri, String localName, String qName,
             Attributes attributes) throws SAXException {
        
         String tagName = localName.length() != 0 ? localName : qName;
         tagName = tagName.toLowerCase().trim();
        
         if(tagName.equals("student")) {
             inStudent  = true;
             curStudent = new Student();
         }
        
         if(inStudent) {
            
             if(tagName.equals("name")) {
                 studentName = true;
             }else if(tagName.equals("age")) {
                 studentAge = true;
             }else if(tagName.equals("sn")) {
                 studentSN = true;
             }
         }
        
     }
    
     @Override
     public void endElement(String uri, String localName, String qName)
             throws SAXException {
        
         String tagName = localName.length() != 0 ? localName : qName;
         tagName = tagName.toLowerCase().trim();
        
         if(tagName.equals("student")) {
             inStudent  = true;
             studentList.add(curStudent);
         }
        
         if(inStudent) {
            
             if(tagName.equals("name")) {
                 studentName = false;
             }else if(tagName.equals("age")) {
                 studentAge = false;
             }else if(tagName.equals("sn")) {
                 studentSN = false;
             }
         }
     }
    
     @Override
     public void characters(char[] ch, int start, int length)
             throws SAXException {
        
         if(studentName) {
             curStudent.setName(curStudent.getName() + new String(ch,start,length));
         }else if (studentAge) {
             curStudent.setAge(Integer.parseInt(new String(ch,start,length)));
         }else if(studentSN) {
             curStudent.setSn(curStudent.getSn() + new String(ch, start, length));           
         }
     }
}
 

 如上面的代码,我们使用了一系列的布尔标志变量来保存文档的遍历状态,先从startElement说起,当我们进入到student节点的时候,我们将inStudent状态设置为true,表示我们已经处于student节点之中,同时创建了一个student对象,相应地,在endElement方法中,我们遇到student结束的时候,会把这个对象添加到我们的studentList中,并将inStudent状态设置为false。同样的,在startElement方法中判断instudent状态,如果当前已经处于student节点中,并且遍历到name,age或者sn节点时,我们也将相应的标志设置为true。这样在遍历的文本节点的时候就可以在characters方法中通过判断这些标志位来为Student对象设置相应的属性。
  注意到,这里curStudent.setName(curStudent.getName() + new String(ch,start,length)),我们用以前的值和新的值连接起来,而不是直接设置curStudent.setName(new String(ch,start,length))。这是因为在遍历<name>.....</name>这中间的文本节点的时候,有些时候这对标签中的内容可能会被看做多个文本节点,比如包含Html实体的情况下 <name>张 三</name>,这里相当于包含了两个文本节点,如果不使用连接的方式而采用直接设置的方式,那么我们最终只能得到最后一次设置的值,因为前面设置的被覆盖了。那么我们最终取得到的名字就是‘三’了。
    这个处理器的核心分功能就算完成了,下面我们还需要增加一个方法,用来返回处理后的内容:

     public List<Student> getStudentList() {
         return studentList;
     }

  完成了处理器之后,我们就可以用刚开始介绍的方法来解析XML文档了:

   SAXParserFactory spf = SAXParserFactory.newInstance();
   SAXParser sp = spf.newSAXParser();
   XMLReader reader = sp.getXMLReader();
 
   List<Student> list;
   reader.setContentHandler(myHandler);           
   reader.parse(new InputSource(new URL(url).openStream()));
 
  list = myHandler.getStudentList();

可以看到,解析完XML文档之后,我们就可以用处理器重的getStudentList方法取得解析后的数据了。
     最后总结一下,SAX并不复杂,只要理解了它的思维方式,我们就可以游刃有余,使它成为我们开发的利器,这篇文章向大家介绍了SAX的一些基本知识,希望能起到一个抛砖引玉的作用,大家能够使用它来创造出更多好的应用,当然可能有一些地方解释的还不是十分完美,如果有一些不好理解的地方,还望大家指出
分享到:
评论

相关推荐

    Objective-c解析XML封装

    2 调用解析类,提供对象名。 3 返回NSMutableDictionary或者NSMutableArray,键值封装。 示例见最后的注释。 XML封装类待续。。。 转载请注明来源,谢谢 ====== XmlResolve.h #import ...

    java 解析装载XML

    // 组装XML推送信息 //编辑xml格式,发送到服务器 //客户端接收xml,并且解析xml //接受xml,读取项目信息

    struts.xml常用配置解析

    struts.xml常用配置解析 网上转载

    如何让Expat支持中文XML

    代码中CCodingConv为gb2312和UTF-8互相转换的类,CGB2312XML为接收解析数据的类,使用SAX方式解析,该类支持gb2312格式的xml文件,当然也可以支持UTF-8格式的xml文件。 为便于理解,Demo程序将解析出的xml数据仍按...

    [转载] JAXB中Java对象和XML之间的转换

    NULL 博文链接:https://dacoolbaby.iteye.com/blog/1667283

    JAVA WEB 开发详解:XML+XSLT+SERVLET+JSP 深入剖析与实例应用.part2

    1.10 xml处理器/解析器 35 1.11 小结 36 第2章 xml名称空间 38 2.1 声明名称空间 38 2.2 名称空间在元素和属性中的运用 39 2.2.1 名称空间在元素中的运用 39 2.2.2 默认名称空间 41 2.2.3 名称空间在属性中...

    JAVA WEB 开发详解:XML+XSLT+SERVLET+JSP 深入剖析与实例应用.part3

    1.10 xml处理器/解析器 35 1.11 小结 36 第2章 xml名称空间 38 2.1 声明名称空间 38 2.2 名称空间在元素和属性中的运用 39 2.2.1 名称空间在元素中的运用 39 2.2.2 默认名称空间 41 2.2.3 名称空间在属性中...

    JAVA WEB 开发详解:XML+XSLT+SERVLET+JSP 深入剖析与实例应用.part4

    1.10 xml处理器/解析器 35 1.11 小结 36 第2章 xml名称空间 38 2.1 声明名称空间 38 2.2 名称空间在元素和属性中的运用 39 2.2.1 名称空间在元素中的运用 39 2.2.2 默认名称空间 41 2.2.3 名称空间在属性中...

    xml 解析,下边是位哥们的全新奉献,这里我转载了,谢谢这位哥们。。

    NULL 博文链接:https://sammyfun.iteye.com/blog/900019

    JAVA WEB 开发详解:XML+XSLT+SERVLET+JSP 深入剖析与实例应用.part5

    1.10 xml处理器/解析器 35 1.11 小结 36 第2章 xml名称空间 38 2.1 声明名称空间 38 2.2 名称空间在元素和属性中的运用 39 2.2.1 名称空间在元素中的运用 39 2.2.2 默认名称空间 41 2.2.3 名称空间在属性中...

    spring源代码解析

    代码解析2,部分摘抄 简单的说,在web容器中,通过ServletContext为Spring的IOC容器提供宿主环境,对应的建立起一个IOC容器的体系。其中,首先需要建立的是根上下文,这个上下文持有的对象可以有业务对象,数据存取...

    JavaScript 解析读取XML文档 实例代码

    应项目之需求,需用JS操作XML文档,遂上网查资料,感觉这篇文章还不错,特转载到此地,与大家共享!

    BlogTutorial.zip

    Xml解析源代码,把TouchXML文件夹copy到工程中,具体操作看一下转载的文章

    JAVA源码 代码一键自动生成工具

    ******原创非转载****** ******支持解析Powerdesiger物理逻辑图****** ******JAVA源码****** 代码一键自动生成工具 可生成Action、JavaBean实体类、Dao及实现类、service及实现类、spring.xml、struts.xml、mybatis....

    JavaBean实体类 配置文件 代码一键自动生成工具

    代码一键自动生成工具 可生成Action、JavaBean实体类、Dao及实现类、service及实现类、spring.xml、struts.xml、mybatis.xml *该工具目前支持3种数据源的生成方式,分别是:JDBC、.table、PDM *JDBC:选择JDBC是只...

    C#学习笔记高级部分(pdf)

    转载前辈的C#学习笔记,跟...使用C#解析简单XML ..................... 25 读XML 文件 ........................... 2 6 用XmlWriter 写XML 文件 ................ 27 插入数据到XML 文档 .................... 29

    android生态之系统篇

    1至11小节皆为解析系统源码目录,12至13小节则为拓展方面。后面将逐渐完善。如有疑问,欢迎在下方评论指出。码字不易,如需转载,请注明出处! 2. build build目录是制定android源码编译规则的地方,详情见如下博客

    asp.net知识库

    Asp.Net(C#)利用XPath解析XML文档示例 XSL .Net框架下的XSLT转换技术简介 一个XSLT的简单例子 XSLXSLT板主题整理 xsl入门的好文章 新手学习XSL的好东西 XSL语法介绍 XSL学习心得 - 调用属性值 XSLT与XML转换的详细...

    AJAX应用的通用流程

    Microsoft 浏览器 Internet Explorer 使用 MSXML 解析器处理 XML。因此如果编写的AJAX应用程序要和 Internet Explorer 打交道,那么必须用一种特殊的方式创建对象。 但并不是这么简单。根据 Internet Explorer 中...

    google search client api for c/c++

    内置XML解析器. 内置gbk/utf-8编码/解码器(包含GBK编码表) 采用Pure C编写,采用标准C接口. 支持http代理. 用户需要在http://api.google.com/createkey申请key 演示程序中的key是一个网友给我的,仅供测试用,...

Global site tag (gtag.js) - Google Analytics