Android 解析xml 文件

xml 文件在各种开发中都广泛应用.Android中也不例外.作为承载数据的一个重要角色.如何读写xml成为一项十分重要的技能.

在Android中,常见的xml解析器分为DOM解析器,SAX解析器,PULL解析器.

将该xml文件放置在assets目录中.

<?xml version="1.0" encoding="utf-8"?>
<persons>
    <person id="1">
        <name>zhangsan</name>
        <age>21</age>>
    </person>
    <person id="2">
        <name>lisi</name>
        <age>22</age>>
    </person>
    <person id="2">
        <name>wangwu</name>
        <age>23</age>>
    </person>
</persons>

DOM 解析器

DOM是基于树形结构的节点和信息片段的集合,允许开发人员使用DOM API遍历xml树,检索所需结构.分析该结构通常需要加载整个文档和构造整个树形结构,然后才可检索和更新节点信息.

在DOM解析过程中,会先把整个xml读入内存中,然后构建一个驻留内存的树结构,这样就可以通过代码使用DOM接口来操作整个树结构.由于DOM在内存中以树形结构存放,因此,检索和更新的效率会更高.但是对于特别大的文档,解析和加载会消耗比较大的资源,如果xml文件比较小,使用DOM也是可行的.

DOM解析的步骤

1.首先利用DocumentBuilderFactory 创建一个DocumentBuilderFactory实例.

        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); 

2.利用DocumentBuilderFactory 创建一个DocumentBuilder实例.

        DocumentBuilder build = factory.newDocumentBuilder() ;

3.加载整个xml文档(Document).

4.获取文档的根节点(Element).

5.获取根节点中所有子节点列表(NodeList).

6.然后获取子节点列表中的需要读取的节点

public List<Person> dom(Context context, String fileName){
        List<Person> persons = new ArrayList<>();
        //1首先利用DocumentBuilderFactory 创建一个DocumentBuilderFactory实例
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        InputStream is = null;
        try{
            //2利用DocumentBuilderFactory 创建一个DocumentBuilder实例
            DocumentBuilder builder = factory.newDocumentBuilder();
            is = context.getResources().getAssets().open(fileName);
            //3加载整个文档(Document)
            Document document = builder.parse(is);
            //4获取文档的根节点(Element)
            Element element = document.getDocumentElement();
            //5获取根节点下所有标签为person的子节点
            NodeList items = element.getElementsByTagName("person");
            for (int i = 0; i < items.getLength(); i++){
                Person person = new Person();
                //得到一个person节点
                Element personNode = (Element) items.item(i);
                //得到person节点中的id的属性值
                person.id = Integer.parseInt(personNode.getAttribute("id"));
                Element name = (Element) personNode.getElementsByTagName("name").item(0);
                person.name = name.getFirstChild().getNodeValue();
                Element age = (Element) personNode.getElementsByTagName("age").item(0);
                person.age = Integer.parseInt(age.getFirstChild().getNodeValue());

//                NodeList childsNode = personNode.getChildNodes();
//                for (int j = 0; j < childsNode.getLength(); j++) {
//                    Node node = childsNode.item(j);
//                    if (node.getNodeType() == Node.ELEMENT_NODE) {
//                        Element childNode = (Element) node;
//                        if (childNode.getNodeName().equals("name")) {
//                            person.name = childNode.getFirstChild().getNodeValue();
//                        } else if (childNode.getNodeName().equals("age")) {
//                            person.age = Integer.parseInt(childNode.getFirstChild().getNodeValue());
//                        }
//                    }
//                }
                persons.add(person);
            }
        }catch (ParserConfigurationException e){
            e.printStackTrace();
        }catch (IOException e){
            e.printStackTrace();
        }catch (SAXException e){
            e.printStackTrace();
        }finally {
            try{
                is.close();
            }catch ( IOException e){
                e.printStackTrace();
            }
        }
        return persons;
    }

SAX 解析器

SAX是一种基于事件的解析器,事件驱动的解析流程方式是从文档的开始解析到文档的结束.不可暂停或倒退.SAX解析器占用内存少,解析速度快.SAX解析的工作原理是对文档进行顺序扫描,当扫描到文档的开始(Document),元素(Element)的开始与结束,文档(Document)的结束.等地方时通知事件处理函数,由事件处理函数作相关的动作.然后继续扫描,直到文档的结束.

SAX解析的步骤

1首先利用SAXParserFactory创建一个SAXParserFactory实例.
                    
SAXParserFactory factory = SAXParserFactory.newInstance();
2  利用SAXParserFactory.newSAXParser()返回一个SAXParser解析器
                    SAXParser parser = factory.newSAXParser();
3  利用SAXParser获取一个事件源对象XMLReader 
4  实例化一个
DefaultHandler对象
5  连接事件源对象XMLReader到事件处理类DefaultHandler中
6  调用XMLReader的parse方法从输入源中获取xml数据
7  通过 
DefaultHandler 返回我们所需的数据

public List<Person> sax(Context context, String fileName){
        //首先利用SAXParserFactory创建一个SAXParserFactory实例
        SAXParserFactory factory = SAXParserFactory.newInstance();
        InputStream is = null;
        try{
            is = context.getResources().getAssets().open(fileName);
            //利用SAXParserFactory.newSAXParser()返回一个SAXParser解析器
            SAXParser parser = factory.newSAXParser();
            //利用SAXParser获取一个事件源对象XMLReader
            XMLReader reader = parser.getXMLReader();
            //实例化一个DefaultHandler对象
            XMLContenHandler handler = new XMLContenHandler();
            //连接事件源对象XMLReader到事件处理类DefaultHandler中
            reader.setContentHandler(handler);
            //调用XMLReader的parse方法从输入源中获取xml数据
            reader.parse(new InputSource(is));
            //通过 DefaultHandler 返回我们所需的数据
            return  handler.getPersons();
        }catch (IOException e){
            e.printStackTrace();
        }catch (SAXException e) {
            e.printStackTrace();
        }catch (ParserConfigurationException e){
            e.printStackTrace();
        }finally {
            try{
                is.close();
            }catch (IOException e){
                e.printStackTrace();
            }
        }
        return null;
    }
class XMLContenHandler extends DefaultHandler{
        private List<Person> persons;
        private Person person;
        private String tagName;

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

        //文档开始时调用
        @Override
        public void startDocument() throws SAXException {
            persons = new ArrayList<>();
        }

        //读取到一个标签开始时调用
        @Override
        public void startElement(String uri, String localName, String qName,
                                 Attributes attributes) throws SAXException {
            if ("person".equals(localName)) {
                person = new Person();
                person.id = Integer.parseInt(attributes.getValue("id"));
            }
            this.tagName = localName;
        }

        //读取到节点内容时回调
        @Override
        public void characters(char[] ch, int start, int length) throws SAXException {
            if (tagName != null) {
                String data = new String(ch, start, length);
                if ("name".equals(tagName)) {
                    person.name = data;
                } else if("age".equals(tagName)){
                    person.age = Integer.parseInt(data);
                }
            }
        }

        //读取到一个标签结束时调用
        @Override
        public void endElement(String uri, String localName, String qName) throws SAXException {
            if ("person".equals(localName)) {
                persons.add(person);
                person = null;
            }
            this.tagName = null;
        }

        //文档结束时调用
        @Override
        public void endDocument() throws SAXException {
            super.endDocument();
        }
    }

PULL 解析器

PULL解析器的运行方式与SAX类似,它提供了相似的事件,如开始元素和结束元素事件.不同的是,PULL解析在解析过程中返回的是数字.且需要我们自己获取产生的事件然后做相应的处理,而不像SAX由处理器触发一些事件.

PULL解析器小巧轻便,解析速度快.简单易用,非常适合在Android设备中使用,Android系统内部在解析xml时也是使用的PULL解析器.Android官方推荐开发者使用PULL解析器.

PULL解析的步骤
1 创建一个XmlPullParser 对象
                        XmlPullParser xmlPullParser = Xml.newPullParser();
2  添加文档信息进XmlPullParser解析器

3  得到个节点信息

public List<Person> pull(Context context, String fileName){
        //获得一个pull解析器
        XmlPullParser parser = Xml.newPullParser();
        List<Person> persons = null;
        Person person = null;
        InputStream is = null;
        try {
            is = context.getResources().getAssets().open(fileName);
            //添加文档信息进pull解析器
            parser.setInput(is, "UTF-8");
            //得到节点信息
            int evtType = parser.getEventType();
            while (evtType != XmlPullParser.END_DOCUMENT) {//如果不是文档结束节点
                switch (evtType) {
                    case XmlPullParser.START_DOCUMENT: //文档的开始
                        persons = new ArrayList<>();
                        break;
                    case XmlPullParser.START_TAG:       //开始标签
                        String tag = parser.getName();
                        if ("person".equals(tag)) {
                            person = new Person();
                            person.id = Integer.parseInt(parser.getAttributeValue(null, "id"));
                        } else if (person != null) {
                            if ("name".equals(tag)) {
                                person.name = parser.nextText();
                            } else if ("age".equals(tag)){
                                person.age = Integer.parseInt(parser.nextText());
                            }
                        }
                        break;
                    case XmlPullParser.END_TAG:       //结束标签
                        if ("person".equals(parser.getName()) && person != null) {
                            persons.add(person);
                            person = null;
                        }
                        break;
                }
                evtType = parser.next();
            }
            return persons;
        } catch (IOException e){
            e.printStackTrace();
        } catch (XmlPullParserException e){
            e.printStackTrace();
        } finally {
            try{
                is.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return null;
    }
以上三种解析xml文件的结果是一样的。


猜你喜欢

转载自blog.csdn.net/xujian197/article/details/79725729