• Java sax、dom、pull解析xml


    -------------------------------------SAX解析xml----------------------------------

    》Sax定义

             SAX是一个解析速度快并且占用内存少的xml解析器,非常适合用于android等移动设备

             SAX全称是Simple API for Xml,既是指一种接口,也是一个软件包

             作为接口,sax是事件驱动型xml解析的一个标准接口

    》Sax特点

            1. 解析效率高,占用内存少

            2.可以随时停止解析

            3.不能载入整个文档到内存

            4.不能写入xml

            5.SAX解析xml文件采用的是事件驱动

            ---sax并不需要解析完 整个文档,在按内容顺序解析文档的过程中,sax会判断当前读到的字符是否合法xml语法中的某部分,如果符合就会触发事件

    》Sax工作原理

             Sax的工作原理简单的说,就是对文档进行顺序扫描,扫描到文档(document)开始与结束,扫描到元素(element)开始、结束等地方时调用事件处理

             处理函数做相应动作,然后继续扫描,直到文档结束。

    》Sax解析文档过程

               1.继承DefaultHandler  ,并实现方法       

               2.创建SAX解析器工厂

               3.获得解析器

               4.获得输入流

               5.使用输入流,和实现接口作参数,调用解析器的解析方法进行解析

    》defaultHandler 接口是实现contentHandler接口

             ContentHandler接口中的常用方法

                     >startDocument()

                                当遇到文档开头的时候,调用这个方法,可以在其中做一些与准备工作

                     >endDocument()

                                 当文档结束的时候,调用这个方法,可以在其中做一些善后工作

                     >startElement(String namespaceURL, String localName, String qName, Attributes atts)

                                 当读到一个开始标签的时候,会触发这个方法。namespaceURL就是命名空间,localName是不带命名空间前缀的标签名,

                                 qName是待命名空间前缀的标签名。通过atts可以得到所有的属性名和相应的值。

                     >endElement(String uri, String localName, String name)

                                当遇到结束标签的时候,调用这个方法

                      >characters(char[] ch, int start, int length)

                                这个方法用来处理在xml文件中读到的内容,第一个参数为文件的字符串内容,后面两个参数是读到的字符串在这个数组中的起始位置和长度,

                                使用new String(ch, start, length)就可以获取内容

    》SAX解析实例

              -------------1.在src下创建xml 文件,并结合成实体类Userinfo.java-------------

    <?xml version="1.0" encoding="UTF-8"?>
    <admins>
    <admin id="1">
    <name>阿龙</name>
    <age>23</age>
    <sex>男</sex>
    <email>along@qq.com</email>
    </admin>
    </admins>

              ----------Userinfo.java----

            String name;
    int age;
    String sex;
    String email;
    String id;

          。。。  生成get、set方法

         --------------------2.创建XmlPaser继承defaultHandler----------------------

      public class XmlPaser extends DefaultHandler{

            //创建user对象为把查到的内容放到里面

            Userinfo user;
    public Userinfo getUser() {
    return user;
    }
    public void setUser(Userinfo user) {
    this.user = user;
    }

             //定义标签变量

            String tagName = null;

            //开始文档处理些准备工作

             public void startDocument() throws SAXException {
    user = new Userinfo();
    super.startDocument();
    }

           

            //读到第一个标签触发

             public void startElement(String uri, String localName, String qName,
    Attributes attributes) throws SAXException {
    tagName = localName;
    if("admin".equals(tagName)){
    user.setId(attributes.getValue(0));
    System.out.println("id:  "+attributes.getValue(0));
    }
    }

            

           //读取文本内容

          public void characters(char[] ch, int start, int length)
    throws SAXException {
    if(tagName!=null){
    if("name".equals(tagName)){
    String str = new String(ch,start,length);
    user.setName(str);
    System.out.println("name:  "+str);
    }else if("age".equals(tagName)){
    String str = new String(ch,start,length);
    user.setAge(Integer.parseInt(str));
    System.out.println("age:   "+str);
    }else if("sex".equals(tagName)){
    String str = new String(ch,start,length);
    user.setSex(str);
    System.out.println("sex:  "+str);
    }else if("email".equals(tagName)){
    String str = new String(ch,start,length);
    user.setEmail(str);
    System.out.println("email:  "+str);
    }
    }
    }

            //遇到结束标签

           public void endElement(String uri, String localName, String qName)
    throws SAXException {
    tagName=null;

    }

            //文档读完

    public void endDocument() throws SAXException {
    super.endDocument();
    }

     }

    ----------------布局文件main省略-----------

    ----------------------3.-类SAXActivity继承Activity----------------

             Button btnOk;

            public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.main);

    btnOk = (Button)this.findViewById(R.id.button1);
            btnOk.setOnClickListener(new OnClickListener() {

    public void onClick(View v){

    //创建解析工厂和解析器

                            SAXParserFactory spf = SAXParserFactory.newInstance();

                            try{

    SAXParser sp = spf.newSAXParser();

                                    //解析

                                   XmlPaser xp = new XmlPaser();

                                    InputStream is = this.getClass().getClassLoader().getResourceAsStream("user.xml");

    sp.parse(is,xp);

    //获得读取到的内容

                                     Userinfo user = xp.getUser();

    //在页面显示

    .................

    }

    }

           });

         }

    ---------------------------------------Dom解析Xml--------------------------------------------

    》DOM简介

            dom全称Document Object Model ,为xml文档的已解析版本定义了一组接口。解析器读入整个文档,然后构建一个主流内存的树结构,

             然后代码就可以使用dom接口来操作这个树结构

    》DOM的特点

             >优点

                      1.整个文档树在内存中,便于操作;支持删除、修改、重新排列等多种功能

                      2.通过树形结构存取xml文档

                      3.可以在树的某个节点上向前或向后移动

               >缺点

                      1.将整个文档调入内存(包括无用的节点),浪费时间和空间

                >适用场合

                      一旦解析了文档还需多次访问这些数据;硬件资源充足(内存,cpu)

    》DOM解析步骤

          1.创建解析器工厂

          2.获得解析器工厂

          3.接受一个xml文档作为输入参数名,并得到一个xml的文档对象(Document)

          4.操作文档对象

    》解析实例:

    -----------------------1.创建要解析的xml文件、和实体类(Person)---------------------------

    <?xml version="1.0" encoding="utf-8"?>
    <users>
    <user id="1">
    <name>Tom</name>
    <age>19</age>
    </user>
    <user id="2">
    <name>Jaary</name>
    <age>18</age>
    </user>
    </users>

    实体类 略

    -----------------------2. Dom解析(DomService.java)-----------------------------------

    public List<Person> getPersons(InputStream input) throws Throwable{

    //获得解析器工厂

             DocumentBuilderFactory    factory = DocumentBuilderFactory.newInstance();

             //获得解析器

              DocumentBuilder builder = factory.newDocumentBuilder();

            //进行解析

             Document  doc = builder.parse(input);

            List<Person> personlist = new new ArrayList<Person>();

           //获得所有叫user的节点

            NodeList  list = doc.getElementsByTagName(user);

            String id="";
    String name="";
    String age="";
    for(int i=0;i<list.getLength();i++){
    //取得第i个user节点
    Element node=(Element)list.item(i);
    Person p=new Person();
    //获取id属性
    id=node.getAttribute("id");
    //获得user节点下的子节点列表
    NodeList userList=node.getChildNodes();
    for(int j=0;j<userList.getLength();j++){
    //判断是否是元素节点,name和age属于元素节点
    if(userList.item(j).getNodeType()==Node.ELEMENT_NODE){

    Element childNode=(Element)userList.item(j);
    if("name".equals(childNode.getNodeName())){
    name=childNode.getFirstChild().getNodeValue();
    }
    else if("age".equals(childNode.getNodeName())){
    age=childNode.getFirstChild().getNodeValue();
    }
    p.setName(name);
    p.setAge(age);
    p.setId(Integer.parseInt(id));
    }

    }

    personList.add(p);
    }
    return personList;

    }

    -------------------------3.Activity01继承Activity类----------------------------------------------------

     public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.main);
            
            InputStream is=this.getClass().getClassLoader().getResourceAsStream("test.xml");
            DomService dom=new DomService();
            
            try {
    List<Person> ps=dom.getPersons(is);
    for(Person p:ps){
    System.out.println(p.getId());
    System.out.println(p.getName());
    System.out.println(p.getAge());
    }
    } catch (Exception e) {
    e.printStackTrace();
    }
        }

    --------------------------------------pull解析-----------------------------

    》pull解析器简介

            1.pull解析器是android内置的解析器,解析原理与sax类似

            2.pull它提供了类似的事件。

                  如:开始元素和结束元素事件,使用parse.next()可以进入下一个元素并触发相应的事件,事件将作为数值代码被发送

                          因此可以使用一个switch对感兴趣的事件进行处理。当元素开始解析时,调用parser.nextText()方法获取下一个Text类型节点的值 

    》pull与sax的不同之处

              1.pull读取xml文件后触发相应的事件调用方法返回的是数字。

              2.pull可以在程序中控制,想解析到哪里就可以停止到哪里

              3.Android中更推荐使用pull解析

    》pull解析步骤

          1.创建解析器对象

              XmlPullParser paser = Xml.newPullParser();

          2.进行解析

                 paser.setInput(input,"utf-8");

          3.产生第一个解析事件

                  int eventType = paser.getEventType();

           4.可以使用循环判断是否继续解析

                    while(eventType!=XmlPullParser.END_DOCUMENT){}

    》解析实例

    -------------------1。创建xml.及实例对象(Person.java)----------------略

    --------------------2.pull解析(PullService .java)----------------------

    List<Person> getAlPerson(InputStream is) throws XmlPullParserException, IOException{

    List<Person> persons=null;
    Person p=null;
    XmlPullParser parser=Xml.newPullParser();
    parser.setInput(is,"utf-8");
    //获得事件类型
    int type=parser.getEventType();
    while(type!=XmlPullParser.END_DOCUMENT){

    switch(type){

    case XmlPullParser.START_DOCUMENT://文档开始
    persons=new ArrayList<Person>();
    break;
    case XmlPullParser.START_TAG://元素开始
    if(parser.getName().equals("user")){

    p=new Person();
    String id=parser.getAttributeValue(0);
    p.setId(Integer.parseInt(id));
    }
    else if(parser.getName().equals("name")){
    if(p!=null){

    String name=parser.nextText();
    p.setName(name);
    }
    }
    else if(parser.getName().equals("age")){

    String age=parser.nextText();
    p.setAge(age);
    }
    break;
    case XmlPullParser.END_TAG:
    if("user".equals(parser.getName())){

    persons.add(p);
    p=null;
    }
    break;

    }
    type=parser.next();
    }
    return persons;
    }
    }

    ------------------------------------Activity类-----------------------------------

     public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.main);
            
            InputStream is=this.getClass().getClassLoader().getResourceAsStream("test.xml");
            PullService pps=new PullService();
            
            try {
    List<Person> ps=pps.getPersons(is);
    for(Person p:ps){
    System.out.println(p.getId());
    System.out.println(p.getName());
    System.out.println(p.getAge());
    }
    } catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    } catch (XmlPullParserException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }
        }

    SAX、DOM、PULL的比较

    SAX、DOM、PULL各有自己的特点,具体操作XML的时候该如何选择呢?

    1.内存占用

    这是一个根本性问题。由于Android手机性能相对于现在的应用操作还是有限的,程序对内存的占用直接影响到了解析XML的速度。在这点上,SAX、Pull以它们比DOM占用更少的内存的解析方式,更适合于Android手机开发。

    2.编程方式

    SAX采用事件驱动,在相应事件触发的时候,会调用用户编写好的方法。也就是说,每解析一类XML,就要编写一个新的适合该类XML的处理类。这显然不是一个好的解决办法,尽管其在解析速度上是那么优秀。而这点,DOM因为是W3C的规范。所以被更多程序员所知道和使用。所以在开发过程中,没有太大困难。Pull虽然属于一个小众的,甚至是不为人知的解析器,但是通过上面对其介绍和示例,我们应该能看出它的简洁性。

    3.访问与修改

    由于采用的是流式解析,这就说明它们不能像DOM那样随机访问,XML的其中任意一个节点。并且,SAX并没有提供对文档中加节点的API,更没有删除,修改文档内容的方法。

    4.访问方式

    这是产生它们解析快慢的根本原因。如果把SAX和Pull比喻成一目十行,很快但是是走马观花的阅读方式的话,那么DOM就是逐字逐句的阅读,很慢,但是是过目不忘。这里还要需要注意的是,SAX,Pull解析的方式是同步的,即解析器读到哪里,就对哪里进行处理。而DOM是已经将文件解析好后,供用户提取XML中感兴趣的信息。

    总结:

    出于对内存占用的考虑,推荐使用SAX或者Pull来工作。可是根据它们工作的原理:如果只是需要XML最后的几个节点的相关信息,或者出现反复检索XML文件的情况。那么基本上三者在性能上就没有什么差异,反而在这时,SAX的处理类会使程序显得比其他的实现方式显得臃肿。所以,想做一个高性能的Android软件,还是要多分析,选择合适的工具,才能发挥它的作用。

  • 相关阅读:
    ORA-06553:PLS-306:wrong number or types of arguments in call to ''
    ORA-06577:output parameter not a bind variable
    CSS3之边框属性border
    Linux_LAMP 最强大的动态网站解决方案
    Linux_LAMP 最强大的动态网站解决方案
    Field BSEG-MWSKZ . does not exist in the screen SAPMF05A 0300 Message no. 00349
    mysql group by
    perl 解析JSON
    数组的数组 散列的散列
    HTTP Cookies
  • 原文地址:https://www.cnblogs.com/HaroldTihan/p/4316397.html
Copyright © 2020-2023  润新知