Android解析XML

在Android平台上可以使用Simple API for XML(SAX) 、 Document Object Model(DOM)和Android附带的pull解析器解析XML文件。

下面是本例子要解析的XML文件:itcast.xml

<?xml version="1.0" encoding="UTF-8"?>
<persons>
  <person id="23">
    <name>李明</name>
    <age>30</age>
  </person>
  <person id="20">
    <name>李向梅</name>
    <age>25</age>
  </person>
</persons>

例子定义了一个javabean用于存放上面解析出来的xml内容, 这个javabean为Person,代码:

public class Person {

    private Integer id;
    private String name;
private Short age;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
}

    public Short getAge() {
        return age;
    }

    public void setAge(Short age) {
        this.age = age;
    }
}

1. SAX解析XML文件

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

public static List<Person> readXML(InputStream inStream) {
   try {
            //创建解析器
            SAXParserFactory spf = SAXParserFactory.newInstance();
            SAXParser saxParser = spf.newSAXParser();

            //设置解析器的相关特性,true表示开启命名空间特性
            saxParser.setProperty("http://xml.org/sax/features/namespaces",true);
            XMLContentHandler handler = new XMLContentHandler();
            saxParser.parse(inStream, handler);
            inStream.close();

            return handler.getPersons();
   } catch (Exception e) {
            e.printStackTrace();
   }

  return null;
}

//SAX类:DefaultHandler,它实现了ContentHandler接口。在实现的时候,只需要继承该类,重载相应的方法即可。
public class XMLContentHandler extends DefaultHandler {

            private List<Person> persons = null;
            private Person currentPerson;
            private String tagName = null;//当前解析的元素标签

             public List<Person> getPersons() {
                        return persons;
            }

            //接收文档开始的通知。当遇到文档的开头的时候,调用这个方法,可以在其中做一些预处理的工作。
            @Override
            public void startDocument() throws SAXException {
                        persons = new ArrayList<Person>();
            }

             //接收元素开始的通知。当读到一个开始标签的时候,会触发这个方法。其中namespaceURI表示元素的命名空间;
            //localName表示元素的本地名称(不带前缀);qName表示元素的限定名(带前缀);atts 表示元素的属性集合
            @Override
            public void startElement(String namespaceURI, String localName, String qName, Attributes atts) throws SAXException {

                        if(localName.equals("person")){
                                    currentPerson = new Person();
                                    currentPerson.setId(Integer.parseInt(atts.getValue("id")));
                        }

                        this.tagName = localName;
            }

            //接收字符数据的通知。该方法用来处理在XML文件中读到的内容,第一个参数用于存放文件的内容,
            //后面两个参数是读到的字符串在这个数组中的起始位置和长度,使用new String(ch,start,length)就可以获取内容。
            @Override
            public void characters(char[] ch, int start, int length) throws SAXException {

                        if(tagName!=null){
                                    String data = new String(ch, start, length);
                                    if(tagName.equals("name")){
                                                this.currentPerson.setName(data);
                                    }else if(tagName.equals("age")){
                                                this.currentPerson.setAge(Short.parseShort(data));
                                    }
                        }
            }

             //接收文档的结尾的通知。在遇到结束标签的时候,调用这个方法。其中,uri表示元素的命名空间;
            //localName表示元素的本地名称(不带前缀);name表示元素的限定名(带前缀)
            @Override
            public void endElement(String uri, String localName, String name) throws SAXException {

                        if(localName.equals("person")){
                                    persons.add(currentPerson);
                                    currentPerson = null;
                        }

                        this.tagName = null;
            }
}

2. DOM解析XML文件

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

public static List<Person> readXML(InputStream inStream) {

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

            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();

            try {
                        DocumentBuilder builder = factory.newDocumentBuilder();
                        Document dom = builder.parse(inStream);

                        Element root = dom.getDocumentElement();

                        NodeList items = root.getElementsByTagName("person");//查找所有person节点

                        for (int i = 0; i < items.getLength(); i++) {
                                    Person person = new Person();

                                    //得到第一个person节点
                                    Element personNode = (Element) items.item(i);

                                    //获取person节点的id属性值
                                    person.setId(new Integer(personNode.getAttribute("id")));

                                    //获取person节点下的所有子节点(标签之间的空白节点和name/age元素)
                                    NodeList childsNodes = personNode.getChildNodes();

                                    for (int j = 0; j < childsNodes.getLength(); j++) {
                                                Node node = (Node) childsNodes.item(j); //判断是否为元素类型

                                                if(node.getNodeType() == Node.ELEMENT_NODE){
                                                            Element childNode = (Element) node;

                                                        //判断是否name元素
                                                            if ("name".equals(childNode.getNodeName())) {
                                                                        //获取name元素下Text节点,然后从Text节点获取数据
                                                                       person.setName(childNode.getFirstChild().getNodeValue());                                                                               } else if (“age”.equals(childNode.getNodeName())) {
                                                                        person.setAge(new Short(childNode.getFirstChild().getNodeValue()));
                                                            }
                                                }
                                    }

                                    persons.add(person);
                        }

                        inStream.close();
            } catch (Exception e) {
                        e.printStackTrace();
            }

            return persons;
}

3.Pull解析器解析XML文件

Pull解析器的运行方式与 SAX 解析器相似。它提供了类似的事件,如:开始元素和结束元素事件,使用parser.next()可以进入下一个元素并触发相应事件。事件将作为数值代码被发送,因此可以使用一个switch对感兴趣的事件进行处理。当元素开始解析时,调用parser.nextText()方法可以获取下一个Text类型元素的值。

//读取XML
public static List<Person> readXML(InputStream inStream) {

            XmlPullParser parser = Xml.newPullParser();

            try {
                        parser.setInput(inStream, "UTF-8");
                        int eventType = parser.getEventType();

                        Person currentPerson = null;
                        List<Person> persons = null;

                        while (eventType != XmlPullParser.END_DOCUMENT) {
                                    switch (eventType) {
                                    case XmlPullParser.START_DOCUMENT://文档开始事件,可以进行数据初始化处理
                                                persons = new ArrayList<Person>();
                                                break;

                                     case XmlPullParser.START_TAG://开始元素事件
                                                String name = parser.getName();
                                                if (name.equalsIgnoreCase("person")) {
                                                            currentPerson = new Person();
                                                            currentPerson.setId(new Integer(parser.getAttributeValue(null, "id")));
                                                } else if (currentPerson != null) {
                                                            if (name.equalsIgnoreCase("name")) {
                                                                        currentPerson.setName(parser.nextText());// 如果后面是Text元素,即返回它的值
                                                            } else if (name.equalsIgnoreCase("age")) {
                                                                        currentPerson.setAge(new Short(parser.nextText()));
                                                            }
                                                }
                                                break;

                                    case XmlPullParser.END_TAG://结束元素事件
                                                if (parser.getName().equalsIgnoreCase("person") && currentPerson != null) {
                                                            persons.add(currentPerson);
                                                            currentPerson = null;
                                                }

                                                break;
                                    }

                                     eventType = parser.next();
                        }

            inStream.close();
            return persons;
            } catch (Exception e) {
                        e.printStackTrace();
            }

            return null;
}

//成XML文件
//使用Pull解析器生成一个与itcast.xml文件内容相同的myitcast.xml文件。
public static String writeXML(List<Person> persons, Writer writer){

    XmlSerializer serializer = Xml.newSerializer();

    try {
        serializer.setOutput(writer);
        serializer.startDocument("UTF-8", true);

        //第一个参数为命名空间,如果不使用命名空间,可以设置为null
        serializer.startTag("", "persons");

        for (Person person : persons){
            serializer.startTag("", "person");
            serializer.attribute("", "id", person.getId().toString());
            serializer.startTag("", "name");
            serializer.text(person.getName());
            serializer.endTag("", "name");
            serializer.startTag("", "age");
            serializer.text(person.getAge().toString());
            serializer.endTag("", "age");
            serializer.endTag("", "person");
        }

        serializer.endTag("", "persons");
        serializer.endDocument();

        return writer.toString();
    } catch (Exception e) {
        e.printStackTrace();
    }

    return null;
}

//使用代码如下(生成XML文件):

File xmlFile = new File("myitcast.xml");
FileOutputStream outStream = new FileOutputStream(xmlFile);
OutputStreamWriter outStreamWriter = new OutputStreamWriter(outStream, "UTF-8");
BufferedWriter writer = new BufferedWriter(outStreamWriter);

writeXML(persons, writer);
writer.flush();
writer.close();

//如果只想得到生成的xml内容,可以使用StringWriter:
StringWriter writer = new StringWriter();
writeXML(persons, writer);
String content = writer.toString();

4.SAX和PULL使用

区别为:SAX解析器的工作方式是自动将事件推入事件处理器进行处理,因此你不能控制事件的处理主动结束;而Pull解析器的工作方式为允许你的应用程序代码主动从解析器中获取事件,正因为是主动获取事件,因此可以在满足了需要的条件后不再获取事件,结束解析。     你随便找个sax和pull的例子比较一下就可以发现,pull是一个while循环,随时可以跳出,而sax不是,sax是只要解析了,就必须解析完成。

时间: 2024-08-04 21:09:35

Android解析XML的相关文章

android解析XML总结-SAX、Pull、Dom三种方式

在android开发中,经常用到去解析xml文件,常见的解析xml的方式有一下三种:SAX.Pull.Dom解析方式.最近做了一个android版的CSDN阅读器,用到了其中的两种(sax,pull),今天对android解析xml的这三种方式进行一次总结. xml示例(channels.xml)如下: <?xml version="1.0" encoding="utf-8"?> <channel> <item id="0&q

Android -- 解析xml

简单布局                                                                                      <TextView android:id="@+id/tv_weather" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_cente

详解android解析Xml的三种方式——DOM、SAX以及XMLpull

今天学习了android解析Xml的三种方式——DOM.SAX以及XMLpull,这里对它们进行总结. 如果理解有误,欢迎指正   ^_* 一.DOM方式解析: xml是先把xml文档都读到内存中,然后再用DOM API来访问树形结构,并获取数据.这个写起来很简单,但是很消耗内存.要是数据过大,手机不够牛逼,可能手机直接死机. 常用的DoM接口和类: Document:该接口定义分析并创建DOM文档的一系列方法,它是文档树的根,是操作DOM的基础.Element:该接口继承Node接口,提供了获

(五十七)android解析XML总结(SAX、Pull、Dom三种方式)

一.SAX.DOM.PULL的比较 SAX.DOM.PULL各有自己的特点,具体操作XML的时候该如何选择呢? 1.内存占用 这是一个根本性问题.由于Android手机性能相对于现在的应用操作还是有限的,程序对内存的占用直接影响到了解析XML的速度.在这点上,SAX.Pull以它们比DOM占用更少的内存的解析方式,更适合于Android手机开发. 2.编程方式 SAX采用事件驱动,在相应事件触发的时候,会调用用户编写好的方法.也就是说,每解析一类XML,就要编写一个新的适合该类XML的处理类.这

Android解析XML文档的两种方式的简单对比

Android之所以会用到解析XML文档,不仅与JAVA对XML的解析比较简单,而且还因为XML是Android在网络间传递信息的主要存储方式.下面我简单谈谈Android对XML文档解析的两种方式:dom和sax.dom解析方式是,解析方法将一个XML文件看成是一棵树.由数据结构的知识我们知道对树的处理比较简单,就是对树的节点进行增,删,改,查,这也是dom的一个最大优点.但是,dom方式在解析的时候是一次性就将整个XML文档读进内存,这坏处不用我说了吧,我宝贵的内存是禁不起这么折腾的. sa

Android解析XML之SAX解析器

SAX(Simple API for XML)解析器是一种基于事件的解析器,它的核心是事件处理模式,主要是围绕着事件源以及事件处理器来工作的.当事件源产生事件后,调用事件处理器相应的处理方法,一个事件就可以得到处理.在事件源调用事件处理器中特定方法的时候,还要传递给事件处理器相应事件的状态信息,这样事件处理器才能够根据提供的事件信息来决定自己的行为. SAX解析器的优点是解析速度快,占用内存少.非常适合在Android移动设备中使用. SAX相关类及API DefaultHandler:是一个事

[android]解析XML文件的方法有三种:PULL,DOM,SAM

PULL 的工作原理: XML pull提供了开始元素和结束元素.当某个元素开始时,可以调用parser.nextText从XML文档中提取所有字符数据.当解析到一个文档结束时,自动生成EndDocument事件. 常用的XML pull的接口和类: XmlPullParser:该解析器是一个在org.xmlpull.v1中定义的解析功能的接口. XmlSerializer:它是一个接口,定义了XML信息集的序列. XmlPullParserFactory:这个类用于在XMPULL V1 API

android 解析XML方式(二)

上一节中,我们使用DOM方式解析xml文档,该方式比较符合我们日常思维方式,容易上手,但是它直接把文档调入内存中,比较耗内存.在这里我们可以用另外一种方式解析xml,这个就是SAX方式. SAX即是:Simple API for XML SAX是基于事件驱动的.当然android的事件机制是基于回调函数的,在用SAX解析xml文档时候,在读取到文档开始和结束标签时候就会回调一个事件,在读取到其他节点与内容时候也会回调一个事件. 既然涉及到事件,就有事件源,事件处理器.在SAX接口中,事件源是or

android 解析XML方式(一)

在androd手机中处理xml数据时很常见的事情,通常在不同平台传输数据的时候,我们就可能使用xml,xml是与平台无关的特性,被广泛运用于数据通信中,那么在android中如何解析xml文件数据呢? 通常有三种方式:DOM,SAX,PULL 在这一节中我们使用DOM方式来处理. DOM方式解析xml是先把xml文档都读到内存中,然后再用DOM API来访问树形结构,并获取数据的,但是这样一来,如果xml文件很大呢?手机CPU处理能力当然不能与PC机器比,因此在处理效率方面就相对差了,当然这是对

android 解析XML方式(三)

上一节中,我们使用SAX方式解析xml文档, SAX方式是基于事件驱动的.当然android的事件机制是基于回调函数的.在这一节中,我们用另外一种方式解析xml文档,这种方式也是基于事件驱动的,与SAX方式一样,它就是PULL方式.只不过PULL方式读xml回调方法返回的是数字. 读取到xml的声明返回      START_DOCUMENT;    读取到xml的结束返回       END_DOCUMENT ;    读取到xml的开始标签返回 START_TAG    读取到xml的结束标