Xml解析

XML解析在Android中应用的比较多,很多时候存储数据需要使用到XML。

这里介绍四种XML解析方式,很多地方说是三种xml解析方式(除去第一种原生xml解析),但是这里的XmlResourceParser跟其他三种不知道是否重复:

1、原生XML解析:XmlResourceParser

2、SAX解析器,

3、DOM解析器,

4、PULL解析器

公共接口:

public interface BookParser {

    //解析输入流,得到book对象集合
    public List<Book> parse(InputStream is) throws Exception;

    //序列化Book对象集合,得到xml形式字符串
    public String serialize(List<Book> books) throws Exception;
}

公共实体类:

package com.mfc.xmlutils;

/**
 * Created by Administrator on 2017/8/11.
 */

public class Book {
    private int id;
    private String name;
    private float price;

    public Book() {
    }

    public Book(int id, String name, float price) {
        this.id = id;
        this.name = name;
        this.price = price;
    }

    public int getId() {
        return id;
    }

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

    public String getName() {
        return name;
    }

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

    public float getPrice() {
        return price;
    }

    public void setPrice(float price) {
        this.price = price;
    }

    @Override
    public String toString() {
        return "Book{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", price=" + price +
                '}';
    }
}


一、原生XML解析:XmlResourceParser

books.xml:(这个xml存放在res的xml文件夹里):

<?xml version="1.0" encoding="utf-8"?>
<books>
    <book price="1.0" id="1001">Java</book>
    <book price="89.0" id="1002">Java EE</book>
    <book price="69.0" id="1003">Ajax</book>
</books>


工具类:

package com.mfc.xmlutils;

import android.content.Context;
import android.content.res.XmlResourceParser;

import com.example.administrator.parsexml.R;

import java.util.ArrayList;
import java.util.List;

public class XmlResourceParserUtil {
    private Context context;
    public XmlResourceParserUtil(Context context){
        this.context = context;
    }
    public List<Book> getXmlResource(){
        XmlResourceParser xlp = context.getResources().getXml(R.xml.books);
        try {
            List<Book> books = new ArrayList<Book>();
            Book book = null;
            //循环,如果还没有到xml文档的结尾处
            while (xlp.getEventType() != XmlResourceParser.END_DOCUMENT){
                //如果遇到了开始标签
                if (xlp.getEventType() == XmlResourceParser.START_TAG){
                    //获取标签名
                    String tagName = xlp.getName();
                    //如果遇到Book标签
                    if (tagName.equals("book")){
                        book = new Book();
                        //根据属性名来获取属性值
                        String bookPrice = xlp.getAttributeValue(0);
                        book.setPrice(Float.parseFloat(bookPrice));
                        String id = xlp.getAttributeValue(1);
                        book.setId(Integer.parseInt(id));
                        //获取文本节点的值
                        book.setName(xlp.nextText());
                        books.add(book);
                    }

                }
                xlp.next();
            }
            return books;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
}

activity:

parserButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                XmlResourceParserUtil xmlResourceParserUtil = new XmlResourceParserUtil(SAXParserXmlActivity.this);
                List<Book> books = xmlResourceParserUtil.getXmlResource();
                StringBuilder stringBuilder = new StringBuilder();
                for (Book book : books) {
                    stringBuilder.append(book.toString());
                }
                XMLContent.setText(stringBuilder.toString());
             }
        });

二、SAX解析器:

books.xml(这个xml存放在assets文件夹下):以下几种解析xml的方法都使用的这一个xml

<?xml version="1.0" encoding="utf-8"?>
<books>
    <book>
        <id>1001</id>
        <name>java编程思想</name>
        <price>80.00</price>
    </book>
    <book>
        <id>1002</id>
        <name>Android群英传</name>
        <price>90.00</price>
    </book>
    <book>
        <id>1003</id>
        <name>spring源码解析</name>
        <price>100.00</price>
    </book>
</books>


工具类:

package com.mfc.xmlutils;

import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.AttributesImpl;
import org.xml.sax.helpers.DefaultHandler;

import java.io.InputStream;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.List;

import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Result;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.sax.SAXTransformerFactory;
import javax.xml.transform.sax.TransformerHandler;
import javax.xml.transform.stream.StreamResult;

/**
 * Created by Administrator on 2017/8/11.
 */

public class BookSaxParser implements BookParser {
    @Override
    public List<Book> parse(InputStream is) throws Exception {
        //取得SAXParserFactory实例
        SAXParserFactory factory = SAXParserFactory.newInstance();
        //从factory获取SAXParser实例
        SAXParser parser = factory.newSAXParser();
        //实例化自定义的Handler
        MyHandler myHandler = new MyHandler();
        parser.parse(is,myHandler);
        return myHandler.getBooks();
    }

    @Override
    public String serialize(List<Book> books) throws Exception {
        //取得SAXTransformerFactory实例
        SAXTransformerFactory factory = (SAXTransformerFactory) TransformerFactory.newInstance();
        //从factory获取TransformerHandler实例
        TransformerHandler handler = factory.newTransformerHandler();
        //从handler获取Transformer实例
        Transformer transformer = handler.getTransformer();
        //设置输出采用的编码方式
        transformer.setOutputProperty(OutputKeys.ENCODING,"UTF-8");
        //是否自动添加额外的空白
        transformer.setOutputProperty(OutputKeys.INDENT,"yes");
        //是否忽略xml声明
        transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION,"no");

        StringWriter writer = new StringWriter();
        Result result = new StreamResult(writer);
        handler.setResult(result);

        //代表命名空间的URI,当URI无值时,需设置为空字符串
        String uri = "";
        //命名空间的本地名称(不包含前缀),当没有进行命名空间处理时,需要设置为空字符串
        String localName = "";

        handler.startDocument();;
        handler.startElement(uri,localName,"books",null);

        //负责存放元素的属性信息
        AttributesImpl attrs = new AttributesImpl();
        char[] ch = null;
        for (Book book : books){
            //清空属性列表
            attrs.clear();
            //添加一个名为id的属性(type影响不大,这里设置为String)
            attrs.addAttribute(uri,localName,"id","string",String.valueOf(book.getId()));
            //开始一个book元素,关联上面设定的id属性
            handler.startElement(uri,localName,"book",attrs);
            //开始一个那么属性,没有元素
            handler.startElement(uri,localName,"name",null);
            ch = String.valueOf(book.getName()).toCharArray();
            //设置price元素的文本节点
            handler.characters(ch,0,ch.length);
            handler.endElement(uri,localName,"price");
            handler.endElement(uri,localName,"book");
        }
        handler.endElement(uri,localName,"books");
        handler.endDocument();
        return writer.toString();
    }

    //需要重写DefaultHandler的方法
    private class MyHandler extends DefaultHandler{
        private List<Book> books;
        private Book book;
        private StringBuilder builder;

        //返回解析后得到的Book对象集合

        public List<Book> getBooks() {
            return books;
        }

        //初始化
        @Override
        public void startDocument() throws SAXException {
            super.startDocument();
            books = new ArrayList<Book>();
            builder = new StringBuilder();
        }

        @Override
        public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
            super.startElement(uri, localName, qName, attributes);
            //开始如果遇到了book标签,就新建一个Book对象
            if (localName.equals("book")) {
                book = new Book();
            }
            //将字符长度设置为0,一边重新开始读取元素的字符节点
            builder.setLength(0);
        }

        @Override
        public void characters(char[] ch, int start, int length) throws SAXException {
            super.characters(ch, start, length);
            //将读取的字符数组追加到builder中
            builder.append(ch,start,length);
        }

        @Override
        public void endElement(String uri, String localName, String qName) throws SAXException {
            super.endElement(uri, localName, qName);
            //遇到book标签后,接下来将遇到的标签对应的值放进实体类对应的属性里面
            if (localName.equals("id")){
                book.setId(Integer.parseInt(builder.toString()));
            }else if (localName.equals("name")) {
                book.setName(builder.toString());
            }else if (localName.equals("price")) {
                book.setPrice(Float.parseFloat(builder.toString()));
            }else if (localName.equals("book")) {
                books.add(book);
            }
        }
    }
}

activity:

 parserXmlBySAXButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                try {
                    InputStream is = getAssets().open("books.xml");
                    //创建SaxBookParser实例
                    parserSAX = new BookSaxParser();
                    //解析输入流
                    books = parserSAX.parse(is);
                    StringBuilder stringBuilder = new StringBuilder();
                    for (Book book : books) {
                        stringBuilder.append(book.toString());
                    }
                    XMLContent.setText(stringBuilder.toString());
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
        writerXmlBySAXButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                try {
                    String xml = parserSAX.serialize(books);
                    FileOutputStream fos = openFileOutput("books.xml", Context.MODE_PRIVATE);
                    fos.write(xml.getBytes("UTF-8"));
                    Toast.makeText(SAXParserXmlActivity.this, "写入成功",Toast.LENGTH_LONG).show();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });

三、DOM解析器:

工具类:

package com.mfc.xmlutils;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import java.io.InputStream;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.List;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

/**
 * Created by Administrator on 2017/8/12.
 */

public class BookDomParser implements BookParser {
    @Override
    public List<Book> parse(InputStream is) throws Exception {

        List<Book> books = new ArrayList<Book>();
        //获取DocumentBuilderFactory实例
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        //从factory获取DocumentBuilder实例
        DocumentBuilder builder = factory.newDocumentBuilder();
        //解析输入流,得到Document实例
        Document doc = builder.parse(is);
        Element rootElement = doc.getDocumentElement();
        NodeList items = rootElement.getElementsByTagName("book");
        for (int i=0;i<items.getLength();i++) {
            Book book = new Book();
            Node item = items.item(i);
            NodeList properties = item.getChildNodes();
            for (int j = 0;j<properties.getLength();j++) {
                Node property = properties.item(j);
                String nodeName = property.getNodeName();
                if(nodeName.equals("id")){
                    book.setId(Integer.parseInt(property.getFirstChild().getNodeValue()));
                } else if (nodeName.equals("name")) {
                    book.setName(property.getFirstChild().getNodeValue());
                } else if (nodeName.equals("price")) {
                    book.setPrice(Float.parseFloat(property.getFirstChild().getNodeValue()));
                }

            }
            books.add(book);
        }
        return books;
    }

    @Override
    public String serialize(List<Book> books) throws Exception {
        //获取DocumentBuilderFactory对象
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        DocumentBuilder builder = factory.newDocumentBuilder();
        //由builder创建新文档
        Document doc = builder.newDocument();
        Element rootElement = doc.createElement("books");
        for (Book book : books) {
            Element bookElement = doc.createElement("book");
            bookElement.setAttribute("id",book.getId()+"");
            Element nameElement = doc.createElement("name");
            nameElement.setTextContent(book.getName());
            bookElement.appendChild(nameElement);

            Element priceElement = doc.createElement("price");
            priceElement.setTextContent(book.getPrice()+"");
            bookElement.appendChild(priceElement);

            rootElement.appendChild(bookElement);
        }
        doc.appendChild(rootElement);

        //取得TransformerFactory实例
        TransformerFactory transFactory = TransformerFactory.newInstance();
        //从transFactory获取Transformer实例
        Transformer transformer = transFactory.newTransformer();
        //设置输出采用的编码方式
        transformer.setOutputProperty(OutputKeys.ENCODING,"UTF-8");
        //设置自动添加额外的空白
        transformer.setOutputProperty(OutputKeys.INDENT,"yes");
        //设置忽略xml声明
        transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION,"no");

        StringWriter writer = new StringWriter();

        //表明文档来源是doc
        Source source = new DOMSource(doc);
        //表明目标结果为writer
        Result result = new StreamResult(writer);
        //开始转换
        transformer.transform(source,result);
        return writer.toString();
    }
}

activity:

parserXmlByDOMButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                try {
                    InputStream is = getAssets().open("books.xml");
                    //创建SaxBookParser实例
                    parserDOM = new BookDomParser();
                    //解析输入流
                    books = parserDOM.parse(is);
                    StringBuilder stringBuilder = new StringBuilder();
                    for (Book book : books) {
                        stringBuilder.append(book.toString());
                    }
                    XMLContent.setText(stringBuilder.toString());
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
        writerXmlByDOMButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                try {
                    String xml = parserDOM.serialize(books);
                    FileOutputStream fos = openFileOutput("books.xml", Context.MODE_PRIVATE);
                    fos.write(xml.getBytes("UTF-8"));
                    Toast.makeText(SAXParserXmlActivity.this, "写入成功",Toast.LENGTH_LONG).show();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });

四、PULL解析器

工具类:

package com.mfc.xmlutils;

import android.util.Xml;

import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlSerializer;

import java.io.InputStream;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.List;

/**
 * Created by Administrator on 2017/8/12.
 */

public class BookPullParser implements BookParser {
    @Override
    public List<Book> parse(InputStream is) throws Exception {
        List<Book> books = null;
        Book book = null;
        //从android.util.Xml创建一个XmlPullParser实例
        XmlPullParser parser = Xml.newPullParser();
        //设置输入流,并指明编码方式
        parser.setInput(is,"UTF-8");

        int eventType = parser.getEventType();
        while(eventType != XmlPullParser.END_DOCUMENT){
            switch (eventType){
                case XmlPullParser.START_DOCUMENT:
                    books = new ArrayList<Book>();
                    break;
                case XmlPullParser.START_TAG:
                    if (parser.getName().equals("book")) {
                        book = new Book();
                    }else if (parser.getName().equals("id")){
                        eventType = parser.next();
                        book.setId(Integer.parseInt(parser.getText()));
                    }else if (parser.getName().equals("name")){
                        eventType = parser.next();
                        book.setName(parser.getText());
                    }else if (parser.getName().equals("price")){
                        eventType = parser.next();
                        book.setPrice(Float.parseFloat(parser.getText()));
                    }
                    break;
                case XmlPullParser.END_TAG:
                    if (parser.getName().equals("book")){
                        books.add(book);
                        book = null;
                    }
                    break;
            }
            eventType = parser.next();
        }
        return books;
    }

    @Override
    public String serialize(List<Book> books) throws Exception {
        //由android.util.Xml创建一个XmlSerializer实例
        XmlSerializer serializer = Xml.newSerializer();
        StringWriter writer = new StringWriter();
        //设置输出方式为writer
        serializer.setOutput(writer);
        serializer.startDocument("UTF-8",true);
        serializer.startTag("","books");
        for (Book book : books) {
            serializer.startTag("","book");
            serializer.attribute("","id",book.getId()+"");

            serializer.startTag("","name");
            serializer.text(book.getName());
            serializer.endTag("","name");

            serializer.startTag("", "price");
            serializer.text(book.getPrice() + "");
            serializer.endTag("", "price");

            serializer.endTag("", "book");
        }

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

        return writer.toString();
    }
}

activity:

parserXmlByPULLButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                try {
                    InputStream is = getAssets().open("books.xml");
                    //创建SaxBookParser实例
                    parserPULL = new BookDomParser();
                    //解析输入流
                    books = parserPULL.parse(is);
                    StringBuilder stringBuilder = new StringBuilder();
                    for (Book book : books) {
                        stringBuilder.append(book.toString());
                    }
                    XMLContent.setText(stringBuilder.toString());
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
        writerXmlByPULLButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                try {
                    String xml = parserPULL.serialize(books);
                    FileOutputStream fos = openFileOutput("books.xml", Context.MODE_PRIVATE);
                    fos.write(xml.getBytes("UTF-8"));
                    Toast.makeText(SAXParserXmlActivity.this, "写入成功",Toast.LENGTH_LONG).show();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });

效果图(这里由于使用的真机,所以看不到写入的文件):


对于这几种解析器各有优点,更倾向于PULL解析器,因为SAX解析器操作起来太笨重,DOM不适合文档较大,内存较小的场景,唯有PULL轻巧灵活,速度快,占用内存小,使用非常顺手。


源码下载:http://download.csdn.net/download/fancheng614/9931088

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值