• Android SAX、DOM、Pull解析xml文件剖析与案例讲解


    XML介绍
    XML(Extensible Markup Language) 即可扩展标记语言,与HTML一样,都是SGML(Standard Generalized Markup Language,标准通用标记语言)。XML是跨平台的,依赖于内容的技术,是当前处理结构化文档信息的有利工具。扩展标记语言XML是一种简单的数据存储语言,使用一系列简单的标记描述数据,而这些标记可以用方便的方式建立,虽然XML占用的空间比二进制数据要占用更多的空间,但XML简单且易于使用。
     
    由于XML扩展性强,致使它需要稳定的基础规则来支持扩展。XML语言规则:
    • 起始和结束的标签相匹配
    • 嵌套标签不能相互嵌套
    • 区分大小写
     
     
     
     
    一、使用SAX解析XML
    SAX使用流式处理的方式,当遇到一个标签时,它并不会记录下以前所碰到的标签,也就是说,在startElement()方法中,你所知道的信息,仅仅是当前标签的名字和属性,至于标签的嵌套结构,上层标签的名字,是否有子元素等其他与结构相关的信息,都是不知道的,都需要通过编码来完成。
     
    SAX进行XML解析的整个过程:
     
    SAXParserHandler: ***startDocument()***
    SAXParserHandler: startElement uri: localName:persons qName:persons
    SAXParserHandler: persons***startElement()***
    SAXParserHandler: startElement uri: localName:person qName:person
    SAXParserHandler: attributeName:id   attributeValue:23
    SAXParserHandler: person***startElement()***
    SAXParserHandler: startElement uri: localName:name qName:name
    SAXParserHandler: name***startElement()***
    SAXParserHandler: content: zhangsan
    SAXParserHandler: name***endElement()***
    SAXParserHandler: startElement uri: localName:age qName:age
    SAXParserHandler: age***startElement()***
    SAXParserHandler: content: 21
    SAXParserHandler: age***endElement()***
    SAXParserHandler: person***endElement()***
    SAXParserHandler: startElement uri: localName:person qName:person
    SAXParserHandler: attributeName:id   attributeValue:20
    SAXParserHandler: person***startElement()***
    SAXParserHandler: startElement uri: localName:name qName:name
    SAXParserHandler: name***startElement()***
    SAXParserHandler: content: wagnwu
    SAXParserHandler: name***endElement()***
    SAXParserHandler: startElement uri: localName:age qName:age
    SAXParserHandler: age***startElement()***
    SAXParserHandler: content: 25
    SAXParserHandler: age***endElement()***
    SAXParserHandler: person***endElement()***
    SAXParserHandler: persons***endElement()***
    SAXParserHandler: ***endDocument()***
     
    从上面Log打印的信息可以了解到SAX解析XML的整个过程和顺序。
     
    为简化工作,SAX为DefaultHandler类提供了接口的默认实现,在大多数情况下,为应用程序扩展DefaultHandler并覆盖相关的方法要比直接实现一个接口更容易。
     
    SAX解析xml案例:
     
    1. 创建Android XMLParser工程
     
    2. 创建SAXParserHandler类:
     
    复写方法:startDocument、startElement、characters、endElement、endDocument
     
    3.Person实体类
     
    package com.xml.demo;
    public class Person {
        private Integer id;
        private String name;
        private Short age;
        public Person() {
        }
        public Person(Integer id, String name, Short age) {
            this.id = id;
            this.name = name;
            this.age = age;
        }
        public Person(String name, Short age) {
            this.name = name;
            this.age = 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;
        }
        @Override
        public String toString() {
            return "id=" + id + ",name=" + name + ",age=" + age;
        }
    }
     
    4 .assets est.xml
     
    <?xml version="1.0" encoding="UTF-8"?>
    <persons>
           <person id = "23">
                 <name>zhangsan</name>
                 <age>21</age>
           </person>
           <person id = "20">
                 <name>wangwu</name>
                 <age>25</age>
           </person>
    </persons>
     
    5. SAXParserHandler类:
     
    package com.xml.demo.sax;
     
    import java.util.ArrayList;
    import java.util.List;
     
    import org.xml.sax.Attributes;
    import org.xml.sax.SAXException;
    import org.xml.sax.helpers.DefaultHandler;
     
    import android.util.Log;
     
    import com.xml.demo.Person;
     
    public class SAXParserHandler extends DefaultHandler {
     
        private static final String TAG = "SAXParserHandler";
        private List<Person> persons;
        private String perTag;// 通过此变量,记录前一个标签的名称。
        Person person;// 记录当前Person
     
        public List<Person> getPersons() {
            return persons;
        }
     
        // 该函数只在开始解析文档时执行一次,比较适合处理一些初始化的行为
        public void startDocument() throws SAXException {
            persons = new ArrayList<Person>();
            Log.i(TAG, "***startDocument()***");
        }
     
        public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
            Log.i(TAG, "startElement uri:" + uri + " localName:" + localName + " qName:" + qName);
            if ("person".equals(localName)) {
                for (int i = 0; i < attributes.getLength(); i++) {
                    Log.i(TAG, "attributeName:" + attributes.getLocalName(i) + "   attributeValue:" + attributes.getValue(i));
                    person = new Person();
                    person.setId(Integer.valueOf(attributes.getValue(i)));
                }
            }
            perTag = localName;
            Log.i(TAG, qName + "***startElement()***");
        }
     
        public void characters(char[] ch, int start, int length) throws SAXException {
            String data = new String(ch, start, length).trim();
            if (!"".equals(data.trim())) {
                Log.i(TAG, "content: " + data.trim());
            }
            if ("name".equals(perTag)) {
                person.setName(data);
            } else if ("age".equals(perTag)) {
                person.setAge(new Short(data));
            }
        }
     
        public void endElement(String uri, String localName, String qName) throws SAXException {
            Log.i(TAG, qName + "***endElement()***");
            if ("person".equals(localName)) {
                persons.add(person);
                person = null;
            }
            perTag = null;
        }
     
        public void endDocument() throws SAXException {
            Log.i(TAG, "***endDocument()***");
        }
    }
     
    6.MainActivity类:
     
    package com.xml.demo;
     
    import java.io.IOException;
    import java.io.InputStream;
    import java.util.List;
     
    import javax.xml.parsers.ParserConfigurationException;
    import javax.xml.parsers.SAXParser;
    import javax.xml.parsers.SAXParserFactory;
     
    import org.xml.sax.SAXException;
     
    import android.app.Activity;
    import android.content.res.AssetManager;
    import android.os.Bundle;
    import android.util.Log;
     
    import com.xml.demo.sax.SAXParserHandler;
     
    public class MainActivity extends Activity {
        String TAG = "ZZMainActivity";
     
        private AssetManager mAssetManager;
        private InputStream mInputStream;
     
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            mAssetManager = getApplicationContext().getAssets();
     
            try {
                mInputStream = mAssetManager.open("test.xml");
            } catch (IOException e) {
                e.printStackTrace();
            }
     
            testSAXParser();
        }
     
        private void testSAXParser() {
            SAXParserHandler saxForHandler = new SAXParserHandler();
            SAXParserFactory spf = SAXParserFactory.newInstance();
            SAXParser saxParser = null;
            try {
                saxParser = spf.newSAXParser();
                saxParser.parse(mInputStream, saxForHandler);
                List<Person> persons = saxForHandler.getPersons();
                for (Person person : persons) {
                    Log.i(TAG, person.toString());
                }
            } catch (ParserConfigurationException e) {
                e.printStackTrace();
            } catch (SAXException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
     
    SAX以流的方式接收指定的XML内容。通过上面SAX解析过程,要清楚,遇到哪些字符,会触发哪些事件,触发的顺序又是怎么样。
     
     
    二、使用DOM解析XML(不推荐使用)
    DOX 是一种用于XML文档的对象模型,可用于直接访问XML文档的各个部分。没有涉及回调和复杂的状态管理,然后,DOM实现常常将所有XML节点保存到内存中,这使较大的文档效率低下。
     
    通过DOM将XML文档作为一个树形结构,这种树形街结构也被称为节点树
     
     
    DOM是这样规定的:
    • 整个文档是一个文档节点;
    • 每个XML元素标签是一个元素节点;
    • 包含在XML元素中的文本是文本节点;
    • 每一个XML属性是一个属性节点;
    • 注释属于注释节点。
     
    节点树中的节点之间彼此都有等级关系。
    在节点树中,顶端的节点成为根节点;
    根节点之外的每个节点都有一个父节点;
    节点可以有任何数量的子节点;
    叶子是没有子节点的节点;
    同级节点是拥有相同父节点的节点。
     
     
    示例:
     
    1. DOMParserHandler
     
    package com.xml.demo.dom;
    import java.io.InputStream;
    import java.util.ArrayList;
    import java.util.List;
    import javax.xml.parsers.DocumentBuilder;
    import javax.xml.parsers.DocumentBuilderFactory;
    import org.w3c.dom.Document;
    import org.w3c.dom.Element;
    import org.w3c.dom.Node;
    import org.w3c.dom.NodeList;
    import com.xml.demo.Person;
    public class DOMParserHandler {
        private static final String TAG = "DOMParserHandler";
        public static List<Person> getPersons(InputStream inStream) throws Exception {
            List<Person> persons = new ArrayList<Person>();
            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
            DocumentBuilder builder = factory.newDocumentBuilder();
            Document document = builder.parse(inStream);
            Element root = document.getDocumentElement();
            NodeList personNodes = root.getElementsByTagName("person");
            for (int i = 0; i < personNodes.getLength(); i++) {
                Element personElement = (Element) personNodes.item(i);
                int id = Integer.valueOf(personElement.getAttribute("id"));
                Person person = new Person();
                person.setId(id);
                NodeList childNodes = personElement.getChildNodes();
                for (int y = 0; y < childNodes.getLength(); y++) {
                    if (childNodes.item(y).getNodeType() == Node.ELEMENT_NODE) {
                        if ("name".equals(childNodes.item(y).getNodeName())) {
                            String name = childNodes.item(y).getFirstChild().getNodeValue();
                            person.setName(name);
                        } else if ("age".equals(childNodes.item(y).getNodeName())) {
                            String age = childNodes.item(y).getFirstChild().getNodeValue();
                            person.setAge(new Short(age));
                        }
                    }
                }
                persons.add(person);
            }
            inStream.close();
            return persons;
        }
    }
     
    2.
    package com.xml.demo;
     
    import java.io.IOException;
    import java.io.InputStream;
    import java.util.List;
     
    import android.app.Activity;
    import android.content.res.AssetManager;
    import android.os.Bundle;
    import android.util.Log;
     
    import com.xml.demo.dom.DOMParserHandler;
     
    public class MainActivity extends Activity {
        String TAG = "ZZMainActivity";
     
        private AssetManager mAssetManager;
        private InputStream mInputStream;
     
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            mAssetManager = getApplicationContext().getAssets();
     
            try {
                mInputStream = mAssetManager.open("test.xml");
            } catch (IOException e) {
                e.printStackTrace();
            }
     
            testDOMParser();
        }
     
        private void testDOMParser() {
            try {
                List<Person> persons = DOMParserHandler.getPersons(mInputStream);
                for (Person person : persons) {
                    Log.i(TAG, person.toString());
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
     
    三、使用PULL解析XML(推荐使用这种方式)
    PULL是Android系统内置的解析器,但不仅限于Android使用
     
    Pull解析器的运行方式和SAX解析器相似。它提供了类似的事件,如开始元素和结束元素事件。使用parser.next()可以进入下一个元素并触发相应事件。事件将作为数值代码被发送,因此可以使用一个switch对感兴趣的事件进行选择,然后进行相应处理。当元素开始解析时,调用parser.nextText()方法可以获取下一个Text类型元素的值。
     
    Pull解析器只有一个重要的方法next();它被用来检索下一个事件。而它的事件也仅仅只有5个:
    • START_DOCUMENT(开始解析)
    • START_TAG(开始元素)
    • TEXT(解析文本)
    • END_TAG(结束元素)
    • END_DOCUMENT(结束解析)
     
    解析XML内容的方式与SAX是相似的,同样包括开始元素和结束元素事件,使用parser.next()可以进入下一个元素并触发相应事件。但是他们不同的是,SAX的事件驱动是回调相应方法,需要提供回调的方法,而后在SAX内部自动调用相应的方法。而pull解析器并没有强制要求提供触发的方法。因为它触发的事件并不是一个方法,而是一个数字。至于触发的事件要不要处理,由程序员自己决定。
     
    示例:
    1. PullParserHandler
    package com.xml.demo.pull;
    import java.io.InputStream;
    import java.util.ArrayList;
    import java.util.List;
    import org.xmlpull.v1.XmlPullParser;
    import android.util.Xml;
    import com.xml.demo.Person;
    public class PullParserHandler {
        private static final String TAG = "PullParserHandler";
        public static List<Person> getPersons(InputStream inStream) throws Exception {
            Person person = null;
            List<Person> persons = null;
            XmlPullParser pullParser = Xml.newPullParser();
            pullParser.setInput(inStream, "UTF-8");
            int event = pullParser.getEventType();// 触发第一个事件
            while (event != XmlPullParser.END_DOCUMENT) {
                switch (event) {
                case XmlPullParser.START_DOCUMENT:
                    persons = new ArrayList<Person>();
                    break;
                case XmlPullParser.START_TAG:
                    if ("person".equals(pullParser.getName())) {
                        int id = Integer.valueOf(pullParser.getAttributeValue(0));
                        person = new Person();
                        person.setId(id);
                    }
                    if (person != null) {
                        if ("name".equals(pullParser.getName())) {
                            person.setName(pullParser.nextText());
                        }
                        if ("age".equals(pullParser.getName())) {
                            person.setAge(new Short(pullParser.nextText()));
                        }
                    }
                    break;
                case XmlPullParser.END_TAG:
                    if ("person".equals(pullParser.getName())) {
                        persons.add(person);
                        person = null;
                    }
                    break;
                }
                event = pullParser.next();
            }
            return persons;
        }
    }
     
    说明:
    a. “int event = pullParser.getEventType()”是pull解析器的第一个事件,这个方法的返回值是int类型,这就是前面提到的pull解析器返回的是一个数字,类似于一个信号。那么这些信号都代表什么意思呢?Pull解析器已经定义了这五个常亮,而且对于事件,仅仅只有这5个,如下:
     
    1. START_DOCUMENT(开始解析)
    2. START_TAG(开始元素)
    3. TEXT(解析文本)
    4. END_TAG(结束元素)
    5. END_DOCUMENT(结束解析)
     
    b. pullParser.getEventType()触发了第一个事件,根据XML的语法,也就是从它开始了解析文档。那么,怎么样触发下一个事件呢?要通过parser中最重要的方法:
        pullParser.next()
    注意:该方法是有返回值的,在Pull触发下一个事件的同时,也获得该事件的“信号”。通过获得的信号进行switch操作。
     
    c. pullParser.getAttributeValue获得相应属性的值。它有两种形式,可以通过属性的索引,也可以通过(命名空间,属性名)进行索引。
     
    2. MainActivity
     
    package com.xml.demo;
     
    import java.io.IOException;
    import java.io.InputStream;
    import java.util.List;
     
    import android.app.Activity;
    import android.content.res.AssetManager;
    import android.os.Bundle;
    import android.util.Log;
     
    import com.xml.demo.pull.PullParserHandler;
     
    public class MainActivity extends Activity {
        String TAG = "ZZMainActivity";
     
        private AssetManager mAssetManager;
        private InputStream mInputStream;
     
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            mAssetManager = getApplicationContext().getAssets();
     
            try {
                mInputStream = mAssetManager.open("test.xml");
            } catch (IOException e) {
                e.printStackTrace();
            }
     
            testPullParser();
        }
     
        private void testPullParser() {
            List<Person> persons;
            try {
                persons = PullParserHandler.getPersons(mInputStream);
                if (persons != null) {
                    for (Person person : persons) {
                        Log.i(TAG, person.toString());
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
     
     
    四、使用PULL生成XML
     
    SAX不支持xml文件的修改、生成,下面介绍下如何使用Pull来生成一个XML
    XML中的标签时成对出现的,又开始,必有结束,所以在写入一个startTag()时,笔者习惯紧跟着写入与之相对应的endTag(),这样不至于在复杂的生成结构时,弄错了XML生成结构
     
    示例1:
    1. PullParserHandler.java
     
    package com.xml.demo.pull;
    import java.io.OutputStream;
    import java.util.List;
    import org.xmlpull.v1.XmlSerializer;
    import android.util.Xml;
    import com.xml.demo.Person;
    public class PullParserHandler {
        private static final String TAG = "PullParserHandler";
        public static void save(List<Person> persons, OutputStream outStream) throws Exception {
            XmlSerializer serializer = Xml.newSerializer();
            serializer.setOutput(outStream, "UTF-8");
            serializer.startDocument("UTF-8", true);
            serializer.startTag(null, "persons");
            for (Person person : persons) {
                serializer.startTag(null, "person");
                serializer.attribute(null, "id", person.getId().toString());
                serializer.startTag(null, "name");
                serializer.text(person.getName());
                serializer.endTag(null, "name");
                serializer.startTag(null, "age");
                serializer.text(person.getAge().toString());
                serializer.endTag(null, "age");
                serializer.endTag(null, "person");
            }
            serializer.endTag(null, "persons");
            serializer.endDocument();
            outStream.flush();
            outStream.close();
        }
    }
     
    2. MainActivity.java
     
    package com.xml.demo;
     
    import java.io.File;
    import java.io.FileNotFoundException;
    import java.io.FileOutputStream;
    import java.io.InputStream;
    import java.util.ArrayList;
    import java.util.List;
     
    import android.app.Activity;
    import android.content.res.AssetManager;
    import android.os.Bundle;
     
    import com.xml.demo.pull.PullParserHandler;
     
    public class MainActivity extends Activity {
        String TAG = "ZZMainActivity";
     
        private AssetManager mAssetManager;
        private InputStream mInputStream;
     
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
     
            testSaveXml();
        }
     
        private void testSaveXml() {
            File file = new File(this.getFilesDir(), "toXmlFile.xml");
            FileOutputStream outStream;
            try {
                outStream = new FileOutputStream(file);
                List<Person> persons = new ArrayList<Person>();
                persons.add(new Person(90, "zhangsan", (short) 13));
                persons.add(new Person(35, "wangwu", (short) 23));
                persons.add(new Person(78, "zhaoliu", (short) 33));
                PullParserHandler.save(persons, outStream);
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
     
    上述生成的xml文件保存在  /data/data/com.xml.demo/files目录下:
    <?xml version='1.0' encoding='UTF-8' standalone='yes' ?><persons><person id="90"><name>zhangsan</name><age>13</age></person><person id="35"><name>wangwu</name><age>23</age></person><person id="78"><name>zhaoliu</name><age>33</age></person></persons>
     
     
    示例2:
    使用Android提供的工具类:FastXmlSerializer.java 和 XmlUtils.java 来生成xml文件,生成的xml文件是格式化后的,比较容易阅读,推荐使用
     
    1. 工具类:FastXmlSerializer.java
     
    package com.xml.demo.utils;
     
    import java.io.IOException;
    import java.io.OutputStream;
    import java.io.OutputStreamWriter;
    import java.io.UnsupportedEncodingException;
    import java.io.Writer;
    import java.nio.ByteBuffer;
    import java.nio.CharBuffer;
    import java.nio.charset.Charset;
    import java.nio.charset.CharsetEncoder;
    import java.nio.charset.CoderResult;
    import java.nio.charset.IllegalCharsetNameException;
    import java.nio.charset.UnsupportedCharsetException;
     
    import org.xmlpull.v1.XmlSerializer;
     
    // copy from frameworks/base/core/java/com/android/internal/util/FastXmlSerializer.java 1.6
    /**
    * This is a quick and dirty implementation of XmlSerializer that isn't horribly
    * painfully slow like the normal one. It only does what is needed for the
    * specific XML files being written with it.
    */
    public class FastXmlSerializer implements XmlSerializer {
        private static final String ESCAPE_TABLE[] = new String[] { null, null, null, null, null, null, null, null, // 0-7
                null, null, null, null, null, null, null, null, // 8-15
                null, null, null, null, null, null, null, null, // 16-23
                null, null, null, null, null, null, null, null, // 24-31
                null, null, "&quot;", null, null, null, "&amp;", null, // 32-39
                null, null, null, null, null, null, null, null, // 40-47
                null, null, null, null, null, null, null, null, // 48-55
                null, null, null, null, "&lt;", null, "&gt;", null, // 56-63
        };
     
        private static final int BUFFER_LEN = 8192;
     
        private final char[] mText = new char[BUFFER_LEN];
        private int mPos;
     
        private Writer mWriter;
     
        private OutputStream mOutputStream;
        private CharsetEncoder mCharset;
        private ByteBuffer mBytes = ByteBuffer.allocate(BUFFER_LEN);
     
        private boolean mInTag;
     
        private void append(char c) throws IOException {
            int pos = mPos;
            if (pos >= (BUFFER_LEN - 1)) {
                flush();
                pos = mPos;
            }
            mText[pos] = c;
            mPos = pos + 1;
        }
     
        private void append(String str, int i, final int length) throws IOException {
            if (length > BUFFER_LEN) {
                final int end = i + length;
                while (i < end) {
                    int next = i + BUFFER_LEN;
                    append(str, i, next < end ? BUFFER_LEN : (end - i));
                    i = next;
                }
                return;
            }
            int pos = mPos;
            if ((pos + length) > BUFFER_LEN) {
                flush();
                pos = mPos;
            }
            str.getChars(i, i + length, mText, pos);
            mPos = pos + length;
        }
     
        private void append(char[] buf, int i, final int length) throws IOException {
            if (length > BUFFER_LEN) {
                final int end = i + length;
                while (i < end) {
                    int next = i + BUFFER_LEN;
                    append(buf, i, next < end ? BUFFER_LEN : (end - i));
                    i = next;
                }
                return;
            }
            int pos = mPos;
            if ((pos + length) > BUFFER_LEN) {
                flush();
                pos = mPos;
            }
            System.arraycopy(buf, i, mText, pos, length);
            mPos = pos + length;
        }
     
        private void append(String str) throws IOException {
            append(str, 0, str.length());
        }
     
        private void escapeAndAppendString(final String string) throws IOException {
            final int N = string.length();
            final char NE = (char) ESCAPE_TABLE.length;
            final String[] escapes = ESCAPE_TABLE;
            int lastPos = 0;
            int pos;
            for (pos = 0; pos < N; pos++) {
                char c = string.charAt(pos);
                if (c >= NE)
                    continue;
                String escape = escapes[c];
                if (escape == null)
                    continue;
                if (lastPos < pos)
                    append(string, lastPos, pos - lastPos);
                lastPos = pos + 1;
                append(escape);
            }
            if (lastPos < pos)
                append(string, lastPos, pos - lastPos);
        }
     
        private void escapeAndAppendString(char[] buf, int start, int len) throws IOException {
            final char NE = (char) ESCAPE_TABLE.length;
            final String[] escapes = ESCAPE_TABLE;
            int end = start + len;
            int lastPos = start;
            int pos;
            for (pos = start; pos < end; pos++) {
                char c = buf[pos];
                if (c >= NE)
                    continue;
                String escape = escapes[c];
                if (escape == null)
                    continue;
                if (lastPos < pos)
                    append(buf, lastPos, pos - lastPos);
                lastPos = pos + 1;
                append(escape);
            }
            if (lastPos < pos)
                append(buf, lastPos, pos - lastPos);
        }
     
        public XmlSerializer attribute(String namespace, String name, String value) throws IOException, IllegalArgumentException, IllegalStateException {
            append(' ');
            if (namespace != null) {
                append(namespace);
                append(':');
            }
            append(name);
            append("="");
     
            escapeAndAppendString(value);
            append('"');
            return this;
        }
     
        public void cdsect(String text) throws IOException, IllegalArgumentException, IllegalStateException {
            throw new UnsupportedOperationException();
        }
     
        public void comment(String text) throws IOException, IllegalArgumentException, IllegalStateException {
            throw new UnsupportedOperationException();
        }
     
        public void docdecl(String text) throws IOException, IllegalArgumentException, IllegalStateException {
            throw new UnsupportedOperationException();
        }
     
        public void endDocument() throws IOException, IllegalArgumentException, IllegalStateException {
            flush();
        }
     
        public XmlSerializer endTag(String namespace, String name) throws IOException, IllegalArgumentException, IllegalStateException {
            if (mInTag) {
                append(" /> ");
            } else {
                append("</");
                if (namespace != null) {
                    append(namespace);
                    append(':');
                }
                append(name);
                append("> ");
            }
            mInTag = false;
            return this;
        }
     
        public void entityRef(String text) throws IOException, IllegalArgumentException, IllegalStateException {
            throw new UnsupportedOperationException();
        }
     
        private void flushBytes() throws IOException {
            int position;
            if ((position = mBytes.position()) > 0) {
                mBytes.flip();
                mOutputStream.write(mBytes.array(), 0, position);
                mBytes.clear();
            }
        }
     
        public void flush() throws IOException {
            // Log.i("PackageManager", "flush mPos=" + mPos);
            if (mPos > 0) {
                if (mOutputStream != null) {
                    CharBuffer charBuffer = CharBuffer.wrap(mText, 0, mPos);
                    CoderResult result = mCharset.encode(charBuffer, mBytes, true);
                    while (true) {
                        if (result.isError()) {
                            throw new IOException(result.toString());
                        } else if (result.isOverflow()) {
                            flushBytes();
                            result = mCharset.encode(charBuffer, mBytes, true);
                            continue;
                        }
                        break;
                    }
                    flushBytes();
                    mOutputStream.flush();
                } else {
                    mWriter.write(mText, 0, mPos);
                    mWriter.flush();
                }
                mPos = 0;
            }
        }
     
        public int getDepth() {
            throw new UnsupportedOperationException();
        }
     
        public boolean getFeature(String name) {
            throw new UnsupportedOperationException();
        }
     
        public String getName() {
            throw new UnsupportedOperationException();
        }
     
        public String getNamespace() {
            throw new UnsupportedOperationException();
        }
     
        public String getPrefix(String namespace, boolean generatePrefix) throws IllegalArgumentException {
            throw new UnsupportedOperationException();
        }
     
        public Object getProperty(String name) {
            throw new UnsupportedOperationException();
        }
     
        public void ignorableWhitespace(String text) throws IOException, IllegalArgumentException, IllegalStateException {
            throw new UnsupportedOperationException();
        }
     
        public void processingInstruction(String text) throws IOException, IllegalArgumentException, IllegalStateException {
            throw new UnsupportedOperationException();
        }
     
        public void setFeature(String name, boolean state) throws IllegalArgumentException, IllegalStateException {
            if (name.equals("http://xmlpull.org/v1/doc/features.html#indent-output")) {
                return;
            }
            throw new UnsupportedOperationException();
        }
     
        public void setOutput(OutputStream os, String encoding) throws IOException, IllegalArgumentException, IllegalStateException {
            if (os == null)
                throw new IllegalArgumentException();
            if (true) {
                try {
                    mCharset = Charset.forName(encoding).newEncoder();
                } catch (IllegalCharsetNameException e) {
                    throw (UnsupportedEncodingException) (new UnsupportedEncodingException(encoding).initCause(e));
                } catch (UnsupportedCharsetException e) {
                    throw (UnsupportedEncodingException) (new UnsupportedEncodingException(encoding).initCause(e));
                }
                mOutputStream = os;
            } else {
                setOutput(encoding == null ? new OutputStreamWriter(os) : new OutputStreamWriter(os, encoding));
            }
        }
     
        public void setOutput(Writer writer) throws IOException, IllegalArgumentException, IllegalStateException {
            mWriter = writer;
        }
     
        public void setPrefix(String prefix, String namespace) throws IOException, IllegalArgumentException, IllegalStateException {
            throw new UnsupportedOperationException();
        }
     
        public void setProperty(String name, Object value) throws IllegalArgumentException, IllegalStateException {
            throw new UnsupportedOperationException();
        }
     
        public void startDocument(String encoding, Boolean standalone) throws IOException, IllegalArgumentException, IllegalStateException {
            append("<?xml version='1.0' encoding='utf-8' standalone='" + (standalone ? "yes" : "no") + "' ?> ");
        }
     
        public XmlSerializer startTag(String namespace, String name) throws IOException, IllegalArgumentException, IllegalStateException {
            if (mInTag) {
                append("> ");
            }
            append('<');
            if (namespace != null) {
                append(namespace);
                append(':');
            }
            append(name);
            mInTag = true;
            return this;
        }
     
        public XmlSerializer text(char[] buf, int start, int len) throws IOException, IllegalArgumentException, IllegalStateException {
            if (mInTag) {
                append(">");
                mInTag = false;
            }
            escapeAndAppendString(buf, start, len);
            return this;
        }
     
        public XmlSerializer text(String text) throws IOException, IllegalArgumentException, IllegalStateException {
            if (mInTag) {
                append(">");
                mInTag = false;
            }
            escapeAndAppendString(text);
            return this;
        }
     
    }
     
     
    2. 工具类:XmlUtils.java
     
    package com.xml.demo.utils;
     
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.OutputStream;
    import java.util.ArrayList;
    import java.util.HashMap;
    import java.util.Iterator;
    import java.util.List;
    import java.util.Map;
    import java.util.Set;
     
    import org.xmlpull.v1.XmlPullParser;
    import org.xmlpull.v1.XmlPullParserException;
    import org.xmlpull.v1.XmlSerializer;
     
    import android.util.Xml;
     
    // copy from frameworks/base/core/java/com/android/internal/util/XmlUtils.java 1.6
     
    public class XmlUtils {
     
        public static void skipCurrentTag(XmlPullParser parser) throws XmlPullParserException, IOException {
            int outerDepth = parser.getDepth();
            int type;
            while ((type = parser.next()) != XmlPullParser.END_DOCUMENT && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
            }
        }
     
        public static final int convertValueToList(CharSequence value, String[] options, int defaultValue) {
            if (null != value) {
                for (int i = 0; i < options.length; i++) {
                    if (value.equals(options[i]))
                        return i;
                }
            }
     
            return defaultValue;
        }
     
        public static final boolean convertValueToBoolean(CharSequence value, boolean defaultValue) {
            boolean result = false;
     
            if (null == value)
                return defaultValue;
     
            if (value.equals("1") || value.equals("true") || value.equals("TRUE"))
                result = true;
     
            return result;
        }
     
        public static final int convertValueToInt(CharSequence charSeq, int defaultValue) {
            if (null == charSeq)
                return defaultValue;
     
            String nm = charSeq.toString();
     
            // XXX This code is copied from Integer.decode() so we don't
            // have to instantiate an Integer!
     
            int value;
            int sign = 1;
            int index = 0;
            int len = nm.length();
            int base = 10;
     
            if ('-' == nm.charAt(0)) {
                sign = -1;
                index++;
            }
     
            if ('0' == nm.charAt(index)) {
                // Quick check for a zero by itself
                if (index == (len - 1))
                    return 0;
     
                char c = nm.charAt(index + 1);
     
                if ('x' == c || 'X' == c) {
                    index += 2;
                    base = 16;
                } else {
                    index++;
                    base = 8;
                }
            } else if ('#' == nm.charAt(index)) {
                index++;
                base = 16;
            }
     
            return Integer.parseInt(nm.substring(index), base) * sign;
        }
     
        public static final int convertValueToUnsignedInt(String value, int defaultValue) {
            if (null == value)
                return defaultValue;
     
            return parseUnsignedIntAttribute(value);
        }
     
        public static final int parseUnsignedIntAttribute(CharSequence charSeq) {
            String value = charSeq.toString();
     
            long bits;
            int index = 0;
            int len = value.length();
            int base = 10;
     
            if ('0' == value.charAt(index)) {
                // Quick check for zero by itself
                if (index == (len - 1))
                    return 0;
     
                char c = value.charAt(index + 1);
     
                if ('x' == c || 'X' == c) { // check for hex
                    index += 2;
                    base = 16;
                } else { // check for octal
                    index++;
                    base = 8;
                }
            } else if ('#' == value.charAt(index)) {
                index++;
                base = 16;
            }
     
            return (int) Long.parseLong(value.substring(index), base);
        }
     
        /**
         * Flatten a Map into an output stream as XML. The map can later be read
         * back with readMapXml().
         *
         * @param val
         *            The map to be flattened.
         * @param out
         *            Where to write the XML data.
         *
         * @see #writeMapXml(Map, String, XmlSerializer)
         * @see #writeListXml
         * @see #writeValueXml
         * @see #readMapXml
         */
        public static final void writeMapXml(Map val, OutputStream out) throws XmlPullParserException, java.io.IOException {
            XmlSerializer serializer = new FastXmlSerializer();
            serializer.setOutput(out, "utf-8");
            serializer.startDocument(null, true);
            serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
            writeMapXml(val, null, serializer);
            serializer.endDocument();
        }
     
        /**
         * Flatten a List into an output stream as XML. The list can later be read
         * back with readListXml().
         *
         * @param val
         *            The list to be flattened.
         * @param out
         *            Where to write the XML data.
         *
         * @see #writeListXml(List, String, XmlSerializer)
         * @see #writeMapXml
         * @see #writeValueXml
         * @see #readListXml
         */
        public static final void writeListXml(List val, OutputStream out) throws XmlPullParserException, java.io.IOException {
            XmlSerializer serializer = Xml.newSerializer();
            serializer.setOutput(out, "utf-8");
            serializer.startDocument(null, true);
            serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
            writeListXml(val, null, serializer);
            serializer.endDocument();
        }
     
        /**
         * Flatten a Map into an XmlSerializer. The map can later be read back with
         * readThisMapXml().
         *
         * @param val
         *            The map to be flattened.
         * @param name
         *            Name attribute to include with this list's tag, or null for
         *            none.
         * @param out
         *            XmlSerializer to write the map into.
         *
         * @see #writeMapXml(Map, OutputStream)
         * @see #writeListXml
         * @see #writeValueXml
         * @see #readMapXml
         */
        public static final void writeMapXml(Map val, String name, XmlSerializer out) throws XmlPullParserException, java.io.IOException {
            if (val == null) {
                out.startTag(null, "null");
                out.endTag(null, "null");
                return;
            }
     
            Set s = val.entrySet();
            Iterator i = s.iterator();
     
            out.startTag(null, "map");
            if (name != null) {
                out.attribute(null, "name", name);
            }
     
            while (i.hasNext()) {
                Map.Entry e = (Map.Entry) i.next();
                writeValueXml(e.getValue(), (String) e.getKey(), out);
            }
     
            out.endTag(null, "map");
        }
     
        /**
         * Flatten a List into an XmlSerializer. The list can later be read back
         * with readThisListXml().
         *
         * @param val
         *            The list to be flattened.
         * @param name
         *            Name attribute to include with this list's tag, or null for
         *            none.
         * @param out
         *            XmlSerializer to write the list into.
         *
         * @see #writeListXml(List, OutputStream)
         * @see #writeMapXml
         * @see #writeValueXml
         * @see #readListXml
         */
        public static final void writeListXml(List val, String name, XmlSerializer out) throws XmlPullParserException, java.io.IOException {
            if (val == null) {
                out.startTag(null, "null");
                out.endTag(null, "null");
                return;
            }
     
            out.startTag(null, "list");
            if (name != null) {
                out.attribute(null, "name", name);
            }
     
            int N = val.size();
            int i = 0;
            while (i < N) {
                writeValueXml(val.get(i), null, out);
                i++;
            }
     
            out.endTag(null, "list");
        }
     
        /**
         * Flatten a byte[] into an XmlSerializer. The list can later be read back
         * with readThisByteArrayXml().
         *
         * @param val
         *            The byte array to be flattened.
         * @param name
         *            Name attribute to include with this array's tag, or null for
         *            none.
         * @param out
         *            XmlSerializer to write the array into.
         *
         * @see #writeMapXml
         * @see #writeValueXml
         */
        public static final void writeByteArrayXml(byte[] val, String name, XmlSerializer out) throws XmlPullParserException, java.io.IOException {
     
            if (val == null) {
                out.startTag(null, "null");
                out.endTag(null, "null");
                return;
            }
     
            out.startTag(null, "byte-array");
            if (name != null) {
                out.attribute(null, "name", name);
            }
     
            final int N = val.length;
            out.attribute(null, "num", Integer.toString(N));
     
            StringBuilder sb = new StringBuilder(val.length * 2);
            for (int i = 0; i < N; i++) {
                int b = val[i];
                int h = b >> 4;
                sb.append(h >= 10 ? ('a' + h - 10) : ('0' + h));
                h = b & 0xff;
                sb.append(h >= 10 ? ('a' + h - 10) : ('0' + h));
            }
     
            out.text(sb.toString());
     
            out.endTag(null, "byte-array");
        }
     
        /**
         * Flatten an int[] into an XmlSerializer. The list can later be read back
         * with readThisIntArrayXml().
         *
         * @param val
         *            The int array to be flattened.
         * @param name
         *            Name attribute to include with this array's tag, or null for
         *            none.
         * @param out
         *            XmlSerializer to write the array into.
         *
         * @see #writeMapXml
         * @see #writeValueXml
         * @see #readThisIntArrayXml
         */
        public static final void writeIntArrayXml(int[] val, String name, XmlSerializer out) throws XmlPullParserException, java.io.IOException {
     
            if (val == null) {
                out.startTag(null, "null");
                out.endTag(null, "null");
                return;
            }
     
            out.startTag(null, "int-array");
            if (name != null) {
                out.attribute(null, "name", name);
            }
     
            final int N = val.length;
            out.attribute(null, "num", Integer.toString(N));
     
            for (int i = 0; i < N; i++) {
                out.startTag(null, "item");
                out.attribute(null, "value", Integer.toString(val[i]));
                out.endTag(null, "item");
            }
     
            out.endTag(null, "int-array");
        }
     
        /**
         * Flatten an object's value into an XmlSerializer. The value can later be
         * read back with readThisValueXml().
         *
         * Currently supported value types are: null, String, Integer, Long, Float,
         * Double Boolean, Map, List.
         *
         * @param v
         *            The object to be flattened.
         * @param name
         *            Name attribute to include with this value's tag, or null for
         *            none.
         * @param out
         *            XmlSerializer to write the object into.
         *
         * @see #writeMapXml
         * @see #writeListXml
         * @see #readValueXml
         */
        public static final void writeValueXml(Object v, String name, XmlSerializer out) throws XmlPullParserException, java.io.IOException {
            String typeStr;
            if (v == null) {
                out.startTag(null, "null");
                if (name != null) {
                    out.attribute(null, "name", name);
                }
                out.endTag(null, "null");
                return;
            } else if (v instanceof String) {
                out.startTag(null, "string");
                if (name != null) {
                    out.attribute(null, "name", name);
                }
                out.text(v.toString());
                out.endTag(null, "string");
                return;
            } else if (v instanceof Integer) {
                typeStr = "int";
            } else if (v instanceof Long) {
                typeStr = "long";
            } else if (v instanceof Float) {
                typeStr = "float";
            } else if (v instanceof Double) {
                typeStr = "double";
            } else if (v instanceof Boolean) {
                typeStr = "boolean";
            } else if (v instanceof byte[]) {
                writeByteArrayXml((byte[]) v, name, out);
                return;
            } else if (v instanceof int[]) {
                writeIntArrayXml((int[]) v, name, out);
                return;
            } else if (v instanceof Map) {
                writeMapXml((Map) v, name, out);
                return;
            } else if (v instanceof List) {
                writeListXml((List) v, name, out);
                return;
            } else if (v instanceof CharSequence) {
                // XXX This is to allow us to at least write something if
                // we encounter styled text... but it means we will drop all
                // of the styling information. :(
                out.startTag(null, "string");
                if (name != null) {
                    out.attribute(null, "name", name);
                }
                out.text(v.toString());
                out.endTag(null, "string");
                return;
            } else {
                throw new RuntimeException("writeValueXml: unable to write value " + v);
            }
     
            out.startTag(null, typeStr);
            if (name != null) {
                out.attribute(null, "name", name);
            }
            out.attribute(null, "value", v.toString());
            out.endTag(null, typeStr);
        }
     
        /**
         * Read a HashMap from an InputStream containing XML. The stream can
         * previously have been written by writeMapXml().
         *
         * @param in
         *            The InputStream from which to read.
         *
         * @return HashMap The resulting map.
         *
         * @see #readListXml
         * @see #readValueXml
         * @see #readThisMapXml #see #writeMapXml
         */
        public static final HashMap readMapXml(InputStream in) throws XmlPullParserException, java.io.IOException {
            XmlPullParser parser = Xml.newPullParser();
            parser.setInput(in, null);
            return (HashMap) readValueXml(parser, new String[1]);
        }
     
        /**
         * Read an ArrayList from an InputStream containing XML. The stream can
         * previously have been written by writeListXml().
         *
         * @param in
         *            The InputStream from which to read.
         *
         * @return HashMap The resulting list.
         *
         * @see #readMapXml
         * @see #readValueXml
         * @see #readThisListXml
         * @see #writeListXml
         */
        public static final ArrayList readListXml(InputStream in) throws XmlPullParserException, java.io.IOException {
            XmlPullParser parser = Xml.newPullParser();
            parser.setInput(in, null);
            return (ArrayList) readValueXml(parser, new String[1]);
        }
     
        /**
         * Read a HashMap object from an XmlPullParser. The XML data could
         * previously have been generated by writeMapXml(). The XmlPullParser must
         * be positioned <em>after</em> the tag that begins the map.
         *
         * @param parser
         *            The XmlPullParser from which to read the map data.
         * @param endTag
         *            Name of the tag that will end the map, usually "map".
         * @param name
         *            An array of one string, used to return the name attribute of
         *            the map's tag.
         *
         * @return HashMap The newly generated map.
         *
         * @see #readMapXml
         */
        public static final HashMap readThisMapXml(XmlPullParser parser, String endTag, String[] name) throws XmlPullParserException, java.io.IOException {
            HashMap map = new HashMap();
     
            int eventType = parser.getEventType();
            do {
                if (eventType == parser.START_TAG) {
                    Object val = readThisValueXml(parser, name);
                    if (name[0] != null) {
                        // System.out.println("Adding to map: " + name + " -> " +
                        // val);
                        map.put(name[0], val);
                    } else {
                        throw new XmlPullParserException("Map value without name attribute: " + parser.getName());
                    }
                } else if (eventType == parser.END_TAG) {
                    if (parser.getName().equals(endTag)) {
                        return map;
                    }
                    throw new XmlPullParserException("Expected " + endTag + " end tag at: " + parser.getName());
                }
                eventType = parser.next();
            } while (eventType != parser.END_DOCUMENT);
     
            throw new XmlPullParserException("Document ended before " + endTag + " end tag");
        }
     
        /**
         * Read an ArrayList object from an XmlPullParser. The XML data could
         * previously have been generated by writeListXml(). The XmlPullParser must
         * be positioned <em>after</em> the tag that begins the list.
         *
         * @param parser
         *            The XmlPullParser from which to read the list data.
         * @param endTag
         *            Name of the tag that will end the list, usually "list".
         * @param name
         *            An array of one string, used to return the name attribute of
         *            the list's tag.
         *
         * @return HashMap The newly generated list.
         *
         * @see #readListXml
         */
        public static final ArrayList readThisListXml(XmlPullParser parser, String endTag, String[] name) throws XmlPullParserException, java.io.IOException {
            ArrayList list = new ArrayList();
     
            int eventType = parser.getEventType();
            do {
                if (eventType == parser.START_TAG) {
                    Object val = readThisValueXml(parser, name);
                    list.add(val);
                    // System.out.println("Adding to list: " + val);
                } else if (eventType == parser.END_TAG) {
                    if (parser.getName().equals(endTag)) {
                        return list;
                    }
                    throw new XmlPullParserException("Expected " + endTag + " end tag at: " + parser.getName());
                }
                eventType = parser.next();
            } while (eventType != parser.END_DOCUMENT);
     
            throw new XmlPullParserException("Document ended before " + endTag + " end tag");
        }
     
        /**
         * Read an int[] object from an XmlPullParser. The XML data could previously
         * have been generated by writeIntArrayXml(). The XmlPullParser must be
         * positioned <em>after</em> the tag that begins the list.
         *
         * @param parser
         *            The XmlPullParser from which to read the list data.
         * @param endTag
         *            Name of the tag that will end the list, usually "list".
         * @param name
         *            An array of one string, used to return the name attribute of
         *            the list's tag.
         *
         * @return Returns a newly generated int[].
         *
         * @see #readListXml
         */
        public static final int[] readThisIntArrayXml(XmlPullParser parser, String endTag, String[] name) throws XmlPullParserException, java.io.IOException {
     
            int num;
            try {
                num = Integer.parseInt(parser.getAttributeValue(null, "num"));
            } catch (NullPointerException e) {
                throw new XmlPullParserException("Need num attribute in byte-array");
            } catch (NumberFormatException e) {
                throw new XmlPullParserException("Not a number in num attribute in byte-array");
            }
     
            int[] array = new int[num];
            int i = 0;
     
            int eventType = parser.getEventType();
            do {
                if (eventType == parser.START_TAG) {
                    if (parser.getName().equals("item")) {
                        try {
                            array[i] = Integer.parseInt(parser.getAttributeValue(null, "value"));
                        } catch (NullPointerException e) {
                            throw new XmlPullParserException("Need value attribute in item");
                        } catch (NumberFormatException e) {
                            throw new XmlPullParserException("Not a number in value attribute in item");
                        }
                    } else {
                        throw new XmlPullParserException("Expected item tag at: " + parser.getName());
                    }
                } else if (eventType == parser.END_TAG) {
                    if (parser.getName().equals(endTag)) {
                        return array;
                    } else if (parser.getName().equals("item")) {
                        i++;
                    } else {
                        throw new XmlPullParserException("Expected " + endTag + " end tag at: " + parser.getName());
                    }
                }
                eventType = parser.next();
            } while (eventType != parser.END_DOCUMENT);
     
            throw new XmlPullParserException("Document ended before " + endTag + " end tag");
        }
     
        /**
         * Read a flattened object from an XmlPullParser. The XML data could
         * previously have been written with writeMapXml(), writeListXml(), or
         * writeValueXml(). The XmlPullParser must be positioned <em>at</em> the tag
         * that defines the value.
         *
         * @param parser
         *            The XmlPullParser from which to read the object.
         * @param name
         *            An array of one string, used to return the name attribute of
         *            the value's tag.
         *
         * @return Object The newly generated value object.
         *
         * @see #readMapXml
         * @see #readListXml
         * @see #writeValueXml
         */
        public static final Object readValueXml(XmlPullParser parser, String[] name) throws XmlPullParserException, java.io.IOException {
            int eventType = parser.getEventType();
            do {
                if (eventType == parser.START_TAG) {
                    return readThisValueXml(parser, name);
                } else if (eventType == parser.END_TAG) {
                    throw new XmlPullParserException("Unexpected end tag at: " + parser.getName());
                } else if (eventType == parser.TEXT) {
                    throw new XmlPullParserException("Unexpected text: " + parser.getText());
                }
                eventType = parser.next();
            } while (eventType != parser.END_DOCUMENT);
     
            throw new XmlPullParserException("Unexpected end of document");
        }
     
        private static final Object readThisValueXml(XmlPullParser parser, String[] name) throws XmlPullParserException, java.io.IOException {
            final String valueName = parser.getAttributeValue(null, "name");
            final String tagName = parser.getName();
     
            // System.out.println("Reading this value tag: " + tagName + ", name=" +
            // valueName);
     
            Object res;
     
            if (tagName.equals("null")) {
                res = null;
            } else if (tagName.equals("string")) {
                String value = "";
                int eventType;
                while ((eventType = parser.next()) != parser.END_DOCUMENT) {
                    if (eventType == parser.END_TAG) {
                        if (parser.getName().equals("string")) {
                            name[0] = valueName;
                            // System.out.println("Returning value for " + valueName
                            // + ": " + value);
                            return value;
                        }
                        throw new XmlPullParserException("Unexpected end tag in <string>: " + parser.getName());
                    } else if (eventType == parser.TEXT) {
                        value += parser.getText();
                    } else if (eventType == parser.START_TAG) {
                        throw new XmlPullParserException("Unexpected start tag in <string>: " + parser.getName());
                    }
                }
                throw new XmlPullParserException("Unexpected end of document in <string>");
            } else if (tagName.equals("int")) {
                res = Integer.parseInt(parser.getAttributeValue(null, "value"));
            } else if (tagName.equals("long")) {
                res = Long.valueOf(parser.getAttributeValue(null, "value"));
            } else if (tagName.equals("float")) {
                res = new Float(parser.getAttributeValue(null, "value"));
            } else if (tagName.equals("double")) {
                res = new Double(parser.getAttributeValue(null, "value"));
            } else if (tagName.equals("boolean")) {
                res = Boolean.valueOf(parser.getAttributeValue(null, "value"));
            } else if (tagName.equals("int-array")) {
                parser.next();
                res = readThisIntArrayXml(parser, "int-array", name);
                name[0] = valueName;
                // System.out.println("Returning value for " + valueName + ": " +
                // res);
                return res;
            } else if (tagName.equals("map")) {
                parser.next();
                res = readThisMapXml(parser, "map", name);
                name[0] = valueName;
                // System.out.println("Returning value for " + valueName + ": " +
                // res);
                return res;
            } else if (tagName.equals("list")) {
                parser.next();
                res = readThisListXml(parser, "list", name);
                name[0] = valueName;
                // System.out.println("Returning value for " + valueName + ": " +
                // res);
                return res;
            } else {
                throw new XmlPullParserException("Unknown tag: " + tagName);
            }
     
            // Skip through to end tag.
            int eventType;
            while ((eventType = parser.next()) != parser.END_DOCUMENT) {
                if (eventType == parser.END_TAG) {
                    if (parser.getName().equals(tagName)) {
                        name[0] = valueName;
                        // System.out.println("Returning value for " + valueName +
                        // ": " + res);
                        return res;
                    }
                    throw new XmlPullParserException("Unexpected end tag in <" + tagName + ">: " + parser.getName());
                } else if (eventType == parser.TEXT) {
                    throw new XmlPullParserException("Unexpected text in <" + tagName + ">: " + parser.getName());
                } else if (eventType == parser.START_TAG) {
                    throw new XmlPullParserException("Unexpected start tag in <" + tagName + ">: " + parser.getName());
                }
            }
            throw new XmlPullParserException("Unexpected end of document in <" + tagName + ">");
        }
     
        public static final void beginDocument(XmlPullParser parser, String firstElementName) throws XmlPullParserException, IOException {
            int type;
            while ((type = parser.next()) != parser.START_TAG && type != parser.END_DOCUMENT) {
                ;
            }
     
            if (type != parser.START_TAG) {
                throw new XmlPullParserException("No start tag found");
            }
     
            if (!parser.getName().equals(firstElementName)) {
                throw new XmlPullParserException("Unexpected start tag: found " + parser.getName() + ", expected " + firstElementName);
            }
        }
     
        public static final void nextElement(XmlPullParser parser) throws XmlPullParserException, IOException {
            int type;
            while ((type = parser.next()) != parser.START_TAG && type != parser.END_DOCUMENT) {
                ;
            }
        }
    }
     
    3.  MainActivity.java
     
    package com.xml.demo;
     
    import java.io.File;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.util.ArrayList;
    import java.util.List;
     
    import org.xmlpull.v1.XmlSerializer;
     
    import android.app.Activity;
    import android.content.res.AssetManager;
    import android.os.Bundle;
    import android.util.Log;
     
    import com.xml.demo.utils.FastXmlSerializer;
     
    public class MainActivity extends Activity {
        String TAG = "ZZMainActivity";
     
        private AssetManager mAssetManager;
        private InputStream mInputStream;
     
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            mAssetManager = getApplicationContext().getAssets();
     
            try {
                mInputStream = mAssetManager.open("test.xml");
            } catch (IOException e) {
                e.printStackTrace();
            }
     
            testSaveXmlWithUtils();
        }
     
        private void testSaveXmlWithUtils() { // 生成xml文件
            List<Person> persons = new ArrayList<Person>();
            persons.add(new Person(80, "zhangsan", (short) 13));
            persons.add(new Person(30, "wangwu", (short) 23));
            persons.add(new Person(70, "zhaoliu", (short) 33));
     
            try {
                File file = new File(this.getFilesDir(), "toXmlFile.xml");
                FileOutputStream str = new FileOutputStream(file);
                XmlSerializer serializer = new FastXmlSerializer();
                serializer.setOutput(str, "utf-8");
                serializer.startDocument(null, true);
                serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
     
                serializer.startTag(null, "persons");
                for (Person person : persons) {
                    serializer.startTag(null, "person");
                    serializer.attribute(null, "id", person.getId().toString());
                    serializer.startTag(null, "name");
                    serializer.text(person.getName());
                    serializer.endTag(null, "name");
     
                    serializer.startTag(null, "age");
                    serializer.text(person.getAge().toString());
                    serializer.endTag(null, "age");
     
                    serializer.endTag(null, "person");
                }
                serializer.endTag(null, "persons");
                serializer.endDocument();
                str.flush();
                str.close();
            } catch (IOException e) {
                Log.w(TAG, "IOException:", e);
            }
        }
    }
     
    /data/data/com.xml.demo/files/toXmlFile.xml 文件:
     
    <?xml version='1.0' encoding='utf-8' standalone='yes' ?>
    <persons>
    <person id="80">
    <name>zhangsan</name>
    <age>13</age>
    </person>
    <person id="30">
    <name>wangwu</name>
    <age>23</age>
    </person>
    <person id="70">
    <name>zhaoliu</name>
    <age>33</age>
    </person>
    </persons>
     
    可以看到,通过上述工具类生成的xml文件,没有在同一行显示,比较格式化,看起来比较阅读。此时读取xml文件内容,可以参考 PullParserHandler类的getPersons()方法实现。
     
     
    五、SAX、DOM、Pull的比较
    1. 内存占用:
    SAX、Pull 优于DOM
     
    2. 编程方式
    推荐 Pull 
     
    3.访问方式
    SAX、Pull解析的方式是同步的,即解析器读到哪里,就对哪里进行处理。而DOM是已经将文件解析好后,供用户读取XML中感兴趣的内容。
     
    个人总结:
    推荐使用Android提供的FastXmlSerializer.java和XmlUtils.java来生成xml文件,读取xml文件按照Pull的方式读取即可。
     
     
     
    本篇内容参考:Android 4.0 网络编程详解(王家林著)
     
  • 相关阅读:
    Android 4.1 for Developers
    Frame Animation 帧动画
    07事事精明,人人远离。
    Launcher 拖拽 流程小结『android 2.3 2.2』
    Android开发书籍推荐
    My first App EncryptWheel is in WAITING FOR REVIEW status
    ubuntu安装显卡驱动
    Shell脚本学习笔记(十)文件操作
    Shell脚本学习笔记(四)流程控制
    Shell脚本学习笔记(五)函数
  • 原文地址:https://www.cnblogs.com/onelikeone/p/9987663.html
Copyright © 2020-2023  润新知