android 中的 xml 解析方法

常用的方法有三种 分别是 sax ,dom , pull;

在org 中 org.w3c.dom  、org.w3c.dom.ls、org.xml.sax、org.xml.sax.ext、org.xml.sax.helpers、org.xmlpull.v1、org.xmlpull.v1.sax2 定义了  dom 、sax、pull的接口

在javax中 javax.xml.parsers 中定义了 dom 和 sax 的 解析接口 和工厂 (DocumentBuilder 、 SAXParser 和 DocumentBuilderFactory、SAXParserFactory)

在 android.util 中 定义了 pull 的 工厂(Xml),org中也提供了 pull的工厂 和解析类

1、sax 方法:

/**
 *
 * SAX是一个解析速度快并且占用内存少的xml解析器,非常适合用于Android等移动设备。
 * SAX解析XML文件采用的是事件驱动,也就是说,它并不需要解析完整个文档,在按内容顺序解析文档的过程中,
 * SAX会判断当前读到的字符是否合法XML语法中的某部分,如果符合就会触发事件。
 *     所谓事件,其实就是一些回调方法,这些方法(事件)定义在ContentHandler接口。
*一般需要继承 DefaultHandler 重写里面的回调方法
 */
public
List<Person> saxParser(InputStream is) { try { SAXParserFactory spf = SAXParserFactory.newInstance(); SAXParser saxParser = spf.newSAXParser(); // 创建解析器 SaxHandler handler = new SaxHandler(); saxParser.parse(is, handler); is.close(); return handler.getPersons(); } catch (Exception e) { e.printStackTrace(); } return null; }


2、dom方法:
/**
     *
     * 除了可以使用 SAX解析XML文件,大家也可以使用熟悉的DOM来解析XML文件。
     * DOM解析XML文件时,会将XML文件的所有内容读取到内存中,然后允许您使用DOM API遍历XML树、检索所需的数据。
     * 使用DOM操作XML的代码看起来比较直观,并且,在某些方面比基于SAX的实现更加简单。
     * 但是,因为DOM需要将XML文件的所有内容读取到内存中,所以内存的消耗比较大,
     * 特别对于运行Android的移动设备来说,因为设备的资源比较宝贵,所以建议还是采用SAX来解析XML文件,
     * 当然,如果XML文件的内容比较小采用DOM是可行的。
     *
     * dom方式需要先生成 dom树,然后从中提取需要的内容 sax 直接从字节流中获取需要的内容,并且建立自定义的数据结构
     *
     * @param is
     * @return
     */
    public List<Person> domParser(InputStream is)
    {
        List<Person> persons = new ArrayList<Person>();
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        try
        {
            DocumentBuilder builder = factory.newDocumentBuilder();
            Document dom = builder.parse(is);
            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);
            }
            is.close();
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
        return persons;
    }

3、pull方法

/**
     * 除了可以使用 SAX和DOM解析XML文件,大家也可以使用Android内置的Pull解析器解析XML文件。
     * Pull解析器的运行方式与 SAX 解析器相似。它提供了类似的事件,
     * 如:开始元素和结束元素事件,使用parser.next()可以进入下一个元素并触发相应事件。
     * 事件将作为数值代码被发送,因此可以使用一个switch对感兴趣的事件进行处理。当元素开始解析时,
     * 调用parser.nextText()方法可以获取下一个Text类型元素的值。
     *
     * 但 Xml pull 比 Sax 更简明,而且不需要扫描完整个流。它通过使用 nextext 控制扫描进度
     *
     * @param is
     * @return
     */
    public List<Person> pullParser(InputStream is)
    {
        XmlPullParser parser = Xml.newPullParser();
        try
        {
            parser.setInput(is, "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();
            }
            is.close();
            return persons;
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
        return null;
    }

1、dom 需要读入保存整个文件,生成一颗document 数,然后可以从中选择需要的节点、属性;
2、sax 需要扫描整个文件,并且封装事件驱动
3、pull 不需要扫码整个文件,可以使用nextText控制扫码进度,也是事件驱动,但没有封装。
posted @ 2012-08-06 14:04  lipeil  阅读(682)  评论(0编辑  收藏  举报