`
landyer
  • 浏览: 141985 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

Android开发必备武器,处理XML的利器--SAX快速上手

阅读更多

相信各位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>张&nbsp;三</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的一些基本知识,希望能起到一个抛砖引玉的作用,大家能够使用它来创造出更多好的应用,当然可能有一些地方解释的还不是十分完美,如果有一些不好理解的地方,还望大家指出。:lol 

     另外下面是SAX的一个官方网站,里面有一些介绍和代码示例,英文不错的童鞋可以来这里参考一下:loveliness: 
     http://www.saxproject.org/

 

 

 

 

分享到:
评论

相关推荐

    java解析xml数据---sax解析器

    Java解析XML数据主要涉及到的是对XML文档的读取和处理,SAX(Simple API for XML)解析器是一种基于事件驱动的解析方式,适用于处理大型XML文件。与DOM(Document Object Model)解析器不同,SAX不需要一次性加载...

    perl-XML-SAX-0.99-9.el7.noarch.rpm

    离线安装包,亲测可用

    android----xml Sax解析示例

    SAX(Simple API for XML)是XML的一种解析器,它采用事件驱动的方式处理XML文档,非常适合处理大型或内存有限的设备上的XML文件,如Android手机。 SAX解析的基本原理是,当解析器读取XML文档时,遇到每个元素、...

    XML四种解析方式------DOM SAX JDOM DOM4J

    在处理XML文档时,有多种解析方式,包括DOM、SAX、JDOM和DOM4J。每种解析方式都有其特性和适用场景,下面将详细探讨这四种解析方法。 1. DOM(Document Object Model) DOM解析器将整个XML文档加载到内存中,形成一...

    Android网络之数据解析----SAX方式解析XML数据

    本篇文章将深入探讨如何使用SAX(Simple API for XML)方式解析XML数据,这是Android网络通信中处理XML数据的一种高效方法。 一、XML与JSON数据 XML(eXtensible Markup Language)是一种用于标记数据的语言,它...

    xml.rar_android_android sax_android sax xml_java xml_sax

    - Android中的SAX解析器实现为`org.xml.sax.helpers.DefaultHandler`,开发者需要继承这个类并重写事件处理方法,如`startElement()`、`endElement()`和`characters()`。 - 示例代码:创建一个SAX解析器实例,设置...

    Xml-GET-SAX.zip_get2326

    在"Xml-GET-SAX"项目中,你可能会找到一个示例,演示如何使用GET请求获取XML文件,并用SAX解析器处理接收到的数据。这个例子对于初学者来说是一个很好的起点,可以了解HTTP请求与XML解析的基本结合。 总结,本教程...

    xmlschema-core-2.0.3的jar

    Java的DOM、SAX和StAX等API虽然也能处理XML,但它们不直接支持XML Schema。而XML Schema Core库为Java开发者提供了一个更强大且专业的工具,专门用于XML Schema相关的任务,特别适合在Spring Web服务中使用。 综上...

    QT使用SAX读取xml高效-快速.rar

    QT使用SAX读取xml高效-快速.rar SAX(Simple API for XML) 如果你只想读取并显示整个XML文档,那么SAX是很好的选择,因为它提供了比DOM更简单的接口,并且它不需要将整个XML文档一次性读入内存,这样便可以用来读取...

    xml-apis-1.4.01.jar.zip

    XML(eXtensible Markup Language)是用于存储和传输数据的一种标记语言,广泛应用于Web服务、配置文件和数据交换等领域。...在处理XML问题时,熟悉这些基本概念和API可以帮助快速定位和解决问题,提高开发效率。

    XML-java.rar_XML SAX_sax_sax xml_sax 解析 xml_xml using dom

    本压缩包文件“XML-java.rar”包含了关于使用Java解析XML的实例,特别强调了SAX解析器的使用,并且提到了使用JDOM和JOM4J这两个Java库来处理XML。 1. **DOM解析**:DOM是一种树型结构,它将整个XML文档加载到内存中...

    xml-apis-2.0.2.jar ecside 依赖包之一

    DOM是XML数据的树形表示,允许开发者通过节点操作来处理XML文档,而SAX是一种事件驱动的解析方法,适用于内存有限或需要快速解析大型XML文件的场景。StAX则提供了一种流式处理XML的方式,允许开发者按需读取或写入...

    vtd-xml vtd-xml vtd-xml

    VTD-XML是一种高效、灵活且轻量级的XML处理库,由Vivtek Data Systems公司开发。这个库专门设计用于解析、导航和修改XML文档,尤其在大型XML数据处理中表现出色。VTD(Variable Token Descriptor)是该库的核心概念...

    android使用SAX解析xml

    在Android开发中,XML(可扩展标记语言)是一种常见的数据交换格式,用于传输和存储数据。SAX(Simple API for XML)是一种事件驱动的解析器,适用于处理大型XML文档,因为它不需要将整个文档加载到内存中,而是逐行...

    perl-XML-SAX-1.00-1.el8.noarch(1).rpm

    官方离线安装包,亲测可用

    SAX--XML文件读写

    在Android开发中,由于内存限制和性能优化的需求,通常会选择SAX(Simple API for XML)解析器来读取XML文件,而非DOM(Document Object Model)解析器,因为SAX是基于事件驱动的,它按需逐个处理XML元素,占用内存...

    android学习笔记1--SAX解析XML

    ### Android学习笔记1—SAX解析XML #### SAX解析XML概览 在Android开发中,XML文件被广泛用于布局设计、资源定义等场景。而为了处理这些XML文件,开发者需要了解不同的XML解析技术,其中SAX(Simple API for XML)...

    [Android]使用SAX解析XML文件

    总结,SAX解析XML在Android开发中是一个实用且高效的解决方案,尤其适用于处理大型XML文件。通过创建自定义的事件处理器,可以灵活地解析和处理XML数据,满足各种业务需求。不过,需要注意的是,由于SAX是基于事件的...

    android开发之xml文件操作——SAX

    总的来说,SAX解析器是Android开发中处理XML文件的一种高效方式,尤其适用于处理大型XML文件。通过学习和实践`SAXTest`项目,你可以深入了解XML解析的内部机制,并将其应用到实际项目中,提高应用程序的性能和可维护...

    android 以SAX方式解析xml

    在Android开发中,XML(可扩展标记语言)是一种常见的数据交换格式,用于存储和传输结构化数据。SAX(Simple API for XML)是处理XML的一种事件驱动的解析方法,它以流式的方式逐行读取XML文档,适用于处理大型XML...

Global site tag (gtag.js) - Google Analytics