android解析xml三种方式学习总结

来源:互联网 发布:什么域名代表公司 编辑:程序博客网 时间:2024/06/15 16:52

第一种:DOM方式解析xml

 DOM方式解析xml是先把xml文档都读到内存中,然后再用DOM API来访问树形结构,并获取数据的,但是这样一来,如果xml文件很大呢?手机CPU处理能力当然不能与PC机器比,因此在处理效率方面就相对差了,当然这是对于其他方式处理xml文档而言。

 

  // 获取全部河流数据

    /**

     * 参数fileName:为xml文档路径

     */

    public List<River> getRiversFromXml(String fileName)

    {

        List<River> rivers = new ArrayList<River>();

        DocumentBuilderFactory factory = null;

        DocumentBuilder builder = null;

        Document document = null;

        InputStream inputStream = null;

        // 首先找到xml文件 利用DocumentBuilderFactory创建一个DocumentBuilderFactory实例

        factory = DocumentBuilderFactory.newInstance();

        try

        {

            // 找到xml,并加载文档 利用DocumentBuilderFactory创建DocumentBuilder

            builder = factory.newDocumentBuilder();

            inputStream = this.context.getResources().getAssets().open(fileName);

            // 加载XML文档(Document)

            document = builder.parse(inputStream);

            // 找到根Element

            Element root = document.getDocumentElement();

            NodeList nodes = root.getElementsByTagName(RIVER);

            // 遍历根节点所有子节点,rivers 下所有river

            River river = null;

            for(int i = 0; i < nodes.getLength(); i++)

            {

                river = new River();

                // 获取river元素节点

                Element riverElement = (Element) (nodes.item(i));

                // 获取river中name属性值

                river.setName(riverElement.getAttribute(NAME));   river.setLength(Integer.parseInt(riverElement.getAttribute(LENGTH)));

                // 获取river下introduction标签

                Element introduction = (Element) riverElement.getElementsByTagName(INTRODUCTION).item(0);           river.setIntroduction(introduction.getFirstChild().getNodeValue());

                Element imageUrl = (Element) riverElement.getElementsByTagName(IMAGEURL).item(0);

river.setImageurl(imageUrl.getFirstChild().getNodeValue());

                rivers.add(river);

            }

        }

        catch(IOException e)

        {

            e.printStackTrace();

        }

        catch(SAXException e)

        {

            e.printStackTrace();

        }

        catch(ParserConfigurationException e)

        {

            e.printStackTrace();

        }

        finally

        {

            try

            {

                inputStream.close();

            }

            catch(IOException e)

            {

                e.printStackTrace();

            }

        }

        return rivers;

    }

 

第二种:SAX解析:

SAX即是:Simple API for XML

SAX是基于事件驱动的。当然android的事件机制是基于回调函数的,在用SAX解析xml文档时候,在读取到文档开始和结束标签时候就会回调一个事件,在读取到其他节点与内容时候也会回调一个事件。

既然涉及到事件,就有事件源,事件处理器。在SAX接口中,事件源是org.xml.sax包中的XMLReader,它通过parser()方法来解析XML文档,并产生事件。事件处理器是org.xml.sax包中ContentHanderDTDHanderErrorHandler,以及EntityResolver4个接口

处理思路是:

1:创建SAXParserFactory对象

2: 根据SAXParserFactory.newSAXParser()方法返回一个SAXParser解析器
3:根据SAXParser解析器获取事件源对象XMLReader
4:实例化一个DefaultHandler对象

5:连接事件源对象XMLReader到事件处理类DefaultHandler

6:调用XMLReaderparse方法从输入源中获取到的xml数据

7:通过DefaultHandler返回我们需要的数据集合。

public List<River> parse(String xmlPath)

    {

        List<River> rivers = null;

        

        SAXParserFactory factory = SAXParserFactory.newInstance();

        try

        {

            SAXParser parser = factory.newSAXParser();

            // 获取事件源

            XMLReader xmlReader = parser.getXMLReader();

            // 设置处理器

            RiverHandler handler = new RiverHandler();

            xmlReader.setContentHandler(handler);

            // 解析xml文档

            // xmlReader.parse(new InputSource(new URL(xmlPath).openStream()));

            xmlReader.parse(new InputSource(context.getAssets().open(xmlPath)));

            rivers = handler.getRivers();

        }

        catch(ParserConfigurationException e)

        {

            e.printStackTrace();

        }

        catch(SAXException e)

        {

            e.printStackTrace();

        }

        catch(IOException e)

        {

            e.printStackTrace();

        }

 

        return rivers;

    }

 

第三种:pull解析:

   读取到xml的声明返回      START_DOCUMENT; 
   读取到xml的结束返回       END_DOCUMENT ; 
   读取到xml的开始标签返回 START_TAG 
   读取到xml的结束标签返回 END_TAG 
   读取到xml的文本返回       TEXT 
xml数据结果还是采用我们先前使用的river.xml文件。

采用PULL方式与SAX大同小异,重点在于我们需要知道导航到什么标签时候做什么就行了,依据上一节SAX处理方式的思路,我们也可以在这一节中一样处理,基本方法是:

基本处理方式是:当PULL解析器导航到文档开始标签时就开始实例化list集合用来存贮数据对象。导航到元素开始标签时回判断元素标签类型,如果是river标签,则需要实例化River对象了,如果是其他类型,则取得该标签内容并赋予River对象。当然它也会导航到文本标签,不过在这里,我们可以不用。

 根据以上的解释,我们可以得出以下处理xml文档逻辑:

1:当导航到XmlPullParser.START_DOCUMENT,可以不做处理,当然你可以实例化集合对象等等。

2:当导航到XmlPullParser.START_TAG,则判断是否是river标签,如果是,则实例化river对象,并调用getAttributeValue方法获取标签中属性值。

3:当导航到其他标签,比如Introduction时候,则判断river对象是否为空,如不为空,则取出Introduction中的内容,nextText方法来获取文本节点内容

4:当然啦,它一定会导航到XmlPullParser.END_TAG的,有开始就要有结束嘛。在这里我们就需要判读是否是river结束标签,如果是,则把river对象存进list集合中了,并设置river对象为null.

 

 public List<River> pullParse(String xmlPath)

    {

        List<River> rivers = new ArrayList<River>();

        River river = null;

        InputStream inputStream = null;

        // 获得XmlPullParser解析器

        XmlPullParser xmlParser = Xml.newPullParser();

        try

        {

            // 得到文件流,并设置编码方式

            inputStream = this.context.getResources().getAssets().open(xmlPath);

            xmlParser.setInput(inputStream, "utf-8");

            // 获得解析到的事件类别,这里有开始文档,结束文档,开始标签,结束标签,文本等等事件。

            int evtType = xmlParser.getEventType();

            // 一直循环,直到文档结束

            while(evtType != XmlPullParser.END_DOCUMENT)

            {

                switch(evtType)

                {

                    case XmlPullParser.START_TAG :

                        String tag = xmlParser.getName();

                        // 如果是river标签开始,则说明需要实例化对象了

                        if(tag.equalsIgnoreCase(RIVER))

                        {

                            river = new River();

                            // 取出river标签中的一些属性值

                            river.setName(xmlParser.getAttributeValue(nullNAME));

                            river.setLength(Integer.parseInt(xmlParser.getAttributeValue(nullLENGTH)));

                        }

                        else if(river != null)

                        {

                            // 如果遇到introduction标签,则读取它内容

                            if(tag.equalsIgnoreCase(INTRODUCTION))

                            {

                                river.setIntroduction(xmlParser.nextText());

                            }

                            else if(tag.equalsIgnoreCase(IMAGEURL))

                            {

                                river.setImageurl(xmlParser.nextText());

                            }

                        }

                        break;

 

                    case XmlPullParser.END_TAG :

                        // 如果遇到river标签结束,则把river对象添加进集合中

                        if(xmlParser.getName().equalsIgnoreCase(RIVER) && river != null)

                        {

                            rivers.add(river);

                            river = null;

                        }

                        break;

                    default:

                        break;

                }

                // 如果xml没有结束,则导航到下一个river节点

                evtType = xmlParser.next();

            }

        }

        catch(XmlPullParserException e)

        {

            e.printStackTrace();

        }

        catch(IOException e1)

        {

            e1.printStackTrace();

        }

        return rivers;

    }

0 0
原创粉丝点击