• (转)Android XML解析技术自eoe


    今日继续学习Android中使用Pull的XML解析技术实现对XML文件的解析和创建。由于明天休息,时间比较充裕,所以我也将昨天未总结的SAX解析技术在此做个总结。 

           一、SAX解析技术

           Sax使用的是事件驱动的流式解析技术。事件驱动的流式解析方式是,从文件的开始顺序解析到文档的结束,不可暂停或倒退。当解析到文档的开始或结束、元素的开始或结束等都会触发一个事件,我们在事件处理方法中完成对数据的操作。由此可见,我们需要编写实现了事件接口的类。

          3.XML文件对应的实体Book:

    package eoe.androidxml;
    
    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 [name=" + name + ", price=" + price + "]";
    }
    }
    

      4.Sax解析XML的事件处理类:

           Sax的事件处理类必须实现ContentHandler接口,但我们在这个例子中不需要使用到ContentHandler接口的所有方法,我们仅需要其中的3个方法。所以Sax为我们提供了一个没有进行任何操作的ContentHandler实现类DefaultHandler。我们直接继承DefaultHandler类,并重写我们需要的方法即可。

    package eoe.androidxml.;
    
    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 com.changcheng.androidxml.entity.Book;
    
    public class SaxXmlContentHandler extends DefaultHandler {
    private List books;
    private Book book;
    private String tagName;
    
    public List getBooks() {
    return books;
    
    }
    /**接收文档的开始的通知。*/
    
    @Override
    public void startDocument() throws SAXException {
    this.books = new ArrayList();
    }
    
    /**接收字符数据的通知。*/
    
    @Override
    public void characters(char[] ch, int start, int length)
    throws SAXException {
    if (this.tagName != null) {
    String data = new String(ch, start, length);
    if (this.tagName.equals("name")) {
    this.book.setName(data);
    } else if (this.tagName.equals("price")) {
    this.book.setPrice(Float.parseFloat(data));
    }
    }
    }
    
    /**
    * 接收元素开始的通知。
    * namespaceURI:元素的命名空间
    * localName:元素的本地名称(不带前缀)
    * qName:元素的限定名(带前缀)
    * atts:元素的属性集合
    */
    
    @Override
    public void startElement(String uri, String localName, String qName,
    Attributes attributes) throws SAXException {
    if (localName.equals("book")) {
    book = new Book();
    book.setId(Integer.parseInt(attributes.getValue(0)));
    }
    this.tagName = localName;
    }
    
    /**
    * 接收文档的结尾的通知。
    * uri:元素的命名空间
    * localName:元素的本地名称(不带前缀)
    * name:元素的限定名(带前缀)
    */
    
    @Override
    public void endElement(String uri, String localName, String qName)
    throws SAXException {
    if (localName.equals("book")) {
    this.books.add(this.book);
    }
    this.tagName = null;
    }
    }
    

      5.编写测试Sax解析XML的类

           在创建工程时,生成的AndroidXML.java,并没有被使用到。因为我们使用Android的单元测试,运行上面的程序。

           编写Android单元测试类:

    java代码:

    package eoe.androidxml;
    
    import java.io.InputStream;
    import java.io.StringWriter;
    import java.util.ArrayList;
    import java.util.List;
    import com.changcheng.androidxml.entity.Book;
    import com.changcheng.androidxml.xml.AndoridSaxXml;
    import com.changcheng.androidxml.xml.AndroidPullXML;
    import android.test.AndroidTestCase;
    import android.util.Log;
    
    public class TestAndroidXML extends AndroidTestCase {
    private static final String TAG = "TestAndroidXML";
    
    /**
    * 测试Sax解析XML
    * @throws Throwable
    */
    
    public void testAndroidSaxReadXML() throws Throwable{
    InputStream file = this.getClass().getClassLoader().getResourceAsStream("books.xml");
    try {
    List books = AndoridSaxXml.readXML(file);
    Log.i(TAG, books.toString());
    } catch (Exception e) {
    Log.e(TAG, e.toString());
    }
    }
    }
    

      6.运行测试

           在outline面板中的testAndroidSaxReadXML方法或在TestAndroidXML类的testAndroidSaxReadXML方法上右键->Debug As->Android Junit Test。运行结束后在LogCat面板中查看运行结束。
    关于使用Sax生成XML文档,我在此就不做总结了。下面的Pull技术才是我们进行Android开发的重点。

            二、Pull解析技术

            Pull解析技术与Sax解析技术原理相同,但比Sax解析简单,它们的解析速度和占用的资源差不多。Android内部使用的XML解析技术正是Pull,Android官方推荐开发者们使用Pull解析技术。Pull解析技术是第三方开发的开源技术,它同样可以应用于JavaSE开发。下面我们使用Pull解析技术解析XML文件,然后再使用Pull技术生成XML文件。

           Pull解析XML文档

           1.XML文件
           依然使用上面的books.xml

           2.XML文档对应的实体Book
           依然使用上面的Book.java

           3.Pull解析XML类

    java代码:

    package eoe.xml;
    
    import java.io.InputStream;
    import java.io.Writer;
    import java.util.ArrayList;
    import java.util.List;
    import org.xmlpull.v1.XmlPullParser;
    import org.xmlpull.v1.XmlPullParserFactory;
    import org.xmlpull.v1.XmlSerializer;
    import android.util.Xml;
    import com.changcheng.androidxml.entity.Book;
    
    public class AndroidPullXML {
    public static List readXML(InputStream inputStream,
    String inputEncoding) throws Exception {
    // 创建Pull解析
    XmlPullParserFactory pullParserFactory = XmlPullParserFactory.newInstance();
    XmlPullParser pullParser = pullParserFactory.newPullParser();
    // 解析XML
    pullParser.setInput(inputStream, inputEncoding);
    // 开始
    
    int eventType = pullParser.getEventType();
    List books = null;
    Book book = null;
    while (eventType != XmlPullParser.END_DOCUMENT) {
    String nodeName = pullParser.getName();
    switch (eventType) {
    // 文档开始
    
    case XmlPullParser.START_DOCUMENT:
    books = new ArrayList();
    break;
    // 节点开始
    case XmlPullParser.START_TAG:
    if ("book".equals(nodeName)) {
    book = new Book();
    book.setId(Integer.parseInt(pullParser.getAttributeValue(0)));
    
    } else if ("name".equals(nodeName)) {
    book.setName(pullParser.nextText());
    } else if ("price".equals(nodeName)) {
    book.setPrice(Float.parseFloat(pullParser.nextText()));
    }
    break;
    // 节点结束
    
    case XmlPullParser.END_TAG:
    if ("book".equals(nodeName)) {
    books.add(book);
    book = null;
    }
    break;
    }
    eventType = pullParser.next();
    }
    return books;
    }
    }
    

      4.编写测试Pull解析XML类

    java代码:

    /**
    * 测试Pull解析XML
    * @throws Throwable
    */
    
    public void testAndroidPullReadXML() throws Throwable {
    InputStream file = this.getClass().getClassLoader().getResourceAsStream("books.xml");
    try {
    List books = AndroidPullXML.readXML(file, "UTF-8");
    Log.i(TAG, books.toString());
    } catch (Exception e) {
    Log.e(TAG, e.toString());
    }
    }
    

      5.运行测试

            在outline面板中的testAndroidPullReadXML方法或在TestAndroidXML类的testAndroidPullReadXML方法上右键->Debug As->Android Junit Test。运行结束后在LogCat面板中查看运行结束。

            Pull生成XML文档
            使用Pull生成上面的books.xml文档。

            1.在AndroidPullXML类中添加一个方法:

    java代码:

    public static void writeXML(Writer writer, List books)
    
    throws Exception {
    // 创建XML生成器
    XmlSerializer writexml = Xml.newSerializer();
    writexml.setOutput(writer);
    
    // 生成XML文档
    writexml.startDocument("UTF-8", true);
    writexml.startTag("", "books");
    
    for (Book book : books) {
    // name
    writexml.startTag("", "name");
    writexml.attribute("", "id", book.getId() + "");
    
    writexml.text(book.getName());
    writexml.endTag("", "name");
    
    // price
    writexml.startTag("", "price");
    writexml.text(book.getPrice() + "");
    writexml.endTag("", "price");
    }
    
    //writexml.endTag("", "books");
    }
    

      2.编写测试Pull生成XML方法

    java代码:

    /**
    * 测试Pull生成XML
    * @throws Throwable
    */
    
    public void testAndroidPullWriteXML() throws Throwable {
    // 生成到内存中。(也可以生成到文件中,那就需要定义一个文件输出流。)
    StringWriter writer = new StringWriter();
    // 添加三本书
    
    List books = new ArrayList();
    books.add(new Book(1, "C", 89));
    books.add(new Book(1, "C++", 100));
    books.add(new Book(1, "Java", 87));
    books.add(new Book(1, "JavaEE", 95));
    
    // 生成XML
    AndroidPullXML.writeXML(writer, books);
    
    // 打印结果
    Log.i(TAG, books.toString());
    }
    

      3.运行测试
            在outline面板中的testAndroidPullWriteXML方法或在TestAndroidXML类的testAndroidPullWriteXML方法上右键->Debug As->Android Junit Test。运行结束后在LogCat面板中查看运行结束。

    6.运行测试
            在outline面板中的testAndroidSaxReadXML方法或在TestAndroidXML类的testAndroidSaxReadXML方法上右键->Debug As->Android Junit Test。运行结束后在LogCat面板中查看运行结束。

            关于使用Sax生成XML文档,我在此就不做总结了。下面的Pull技术才是我们进行Android开发的重点。

            二、Pull解析技术
            Pull解析技术与Sax解析技术原理相同,但比Sax解析简单,它们的解析速度和占用的资源差不多。Android内部使用的XML解析技术正是Pull,Android官方推荐开发者们使用Pull解析技术。Pull解析技术是第三方开发的开源技术,它同样可以应用于JavaSE开发。下面我们使用Pull解析技术解析XML文件,然后再使用Pull技术生成XML文件。

            Pull解析XML文档

           1.XML文件
           依然使用上面的books.xml
           2.XML文档对应的实体Book
           依然使用上面的Book.java
           3.Pull解析XML类

    java代码:

    package eoe.xml;
    
    import java.io.InputStream;
    import java.io.Writer;
    import java.util.ArrayList;
    import java.util.List;
    import org.xmlpull.v1.XmlPullParser;
    import org.xmlpull.v1.XmlPullParserFactory;
    import org.xmlpull.v1.XmlSerializer;
    import android.util.Xml;
    import com.changcheng.androidxml.entity.Book;
    
    public class AndroidPullXML {
    public static List readXML(InputStream inputStream,
    String inputEncoding) throws Exception {
    // 创建Pull解析
    XmlPullParserFactory pullParserFactory = XmlPullParserFactory.newInstance();
    
    XmlPullParser pullParser = pullParserFactory.newPullParser();
    
    // 解析XML
    pullParser.setInput(inputStream, inputEncoding);
    
    // 开始
    int eventType = pullParser.getEventType();
    List books = null;
    Book book = null;
    
    while (eventType != XmlPullParser.END_DOCUMENT) {
    String nodeName = pullParser.getName();
    
    switch (eventType) {
    // 文档开始
    case XmlPullParser.START_DOCUMENT:
    books = new ArrayList();
    break;
    
    // 节点开始
    
    case XmlPullParser.START_TAG:
    
    if ("book".equals(nodeName)) {
    book = new Book();
    book.setId(Integer.parseInt(pullParser.getAttributeValue(0)));
    } else if ("name".equals(nodeName)) {
    book.setName(pullParser.nextText());
    } else if ("price".equals(nodeName)) {
    book.setPrice(Float.parseFloat(pullParser.nextText()));
    }
    break;
    
    // 节点结束
    case XmlPullParser.END_TAG:
    if ("book".equals(nodeName)) {
    books.add(book);
    book = null;
    }
    break;
    }
    eventType = pullParser.next();
    }
    return books;
    }
    
    }
    

      4.编写测试Pull解析XML类
           在sax测试类TestAndroidXML中添加一个测试方法:

    java代码:

    /**
    * 测试Pull解析XML
    * @throws Throwable
    */
    
    public void testAndroidPullReadXML() throws Throwable {
    InputStream file = this.getClass().getClassLoader().getResourceAsStream("books.xml");
    try {
    
    List books = AndroidPullXML.readXML(file, "UTF-8");
    Log.i(TAG, books.toString());
    } catch (Exception e) {
    Log.e(TAG, e.toString());
    }
    
    }
    

      5.运行测试
           在outline面板中的testAndroidPullReadXML方法或在TestAndroidXML类的testAndroidPullReadXML方法上右键->Debug As->Android Junit Test。运行结束后在LogCat面板中查看运行结束。

           Pull生成XML文档

           使用Pull生成上面的books.xml文档。

           1.在AndroidPullXML类中添加一个方法:

    java代码:

    public static void writeXML(Writer writer, List books)
    
    throws Exception {
    // 创建XML生成器
    XmlSerializer writexml = Xml.newSerializer();
    writexml.setOutput(writer);
    
    // 生成XML文档
    writexml.startDocument("UTF-8", true);
    writexml.startTag("", "books");
    
    for (Book book : books) {
    
    // name
    writexml.startTag("", "name");
    writexml.attribute("", "id", book.getId() + "");
    writexml.text(book.getName());
    writexml.endTag("", "name");
    
    // price
    writexml.startTag("", "price");
    writexml.text(book.getPrice() + "");
    writexml.endTag("", "price");
    }
    writexml.endTag("", "books");
    
    }
    

      2.编写测试Pull生成XML方法

            在sax测试类TestAndroidXML中添加一个测试方法:

    java代码:

    /**
    * 测试Pull生成XML
    * @throws Throwable
    */
    
    public void testAndroidPullWriteXML() throws Throwable {
    // 生成到内存中。(也可以生成到文件中,那就需要定义一个文件输出流。)
    
    StringWriter writer = new StringWriter();
    // 添加三本书
    
    List books = new ArrayList();
    books.add(new Book(1, "C", 89));
    books.add(new Book(1, "C++", 100));
    books.add(new Book(1, "Java", 87));
    books.add(new Book(1, "JavaEE", 95));
    
    // 生成XML
    AndroidPullXML.writeXML(writer, books);
    
    // 打印结果
    Log.i(TAG, books.toString());
    }
    

      3.运行测试

             在outline面板中的testAndroidPullWriteXML方法或在TestAndroidXML类的testAndroidPullWriteXML方法上右键->Debug As->Android Junit Test。运行结束后在LogCat面板中查看运行结束。

  • 相关阅读:
    SQL 查询第n条到第m条的数据
    Linq 中查询一个表中指定的字段
    归并排序与逆序对
    补码拾遗
    堆排序
    It is time to cut the Gordian Knot!
    蛋疼
    [引]Microsoft Visual Studio .NET 2005 预发行版
    关于VS2005中自动生成TableAdapter的事务处理
    关于释放ASPNET进程的内存占用问题.
  • 原文地址:https://www.cnblogs.com/greywolf/p/3040209.html
Copyright © 2020-2023  润新知