使用Pull解析和生成XML文档

使用Pull解析和生成XML文档的步骤:

  • 我一向不擅长说废话,概念性的东西就不搬运了.接下来我将按照生成->解析的完整步骤演示Pull的使用.由于本人毕业时间不久经验不足,如有错误请各位朋友指出.

根据xml文档中需要定义的内容,或据现有xml的数据结构,将其剖析为java的对象形式.需要注意的是在剖析时一定要理清层级关系.以下是xml数据结构:

<Librarys> 
      <Library id="123"> 
        <name>武汉大学图书馆</name>  
        <address>古庙工业园77号-1-4</address>  
        <books> 
          <book> 
            <name>安琪成长记</name>  
            <price>55</price>  
            <autor>任咏莉</autor> 
          </book>  
          <book> 
            <name>哈喽成长记</name>  
            <price>70</price>  
            <autor>董宁</autor> 
          </book> 
        </books> 
      </Library>  
      <Library id="456"> 
        <name>四川川大学图书馆</name>  
        <address>曲阜街147号-12-7</address>  
        <books> 
          <book> 
            <name>雷欧成长记</name>  
            <price>71</price>  
            <autor>夏炎岩</autor> 
          </book>  
          <book> 
            <name>奥迪成长记</name>  
            <price>72</price>  
            <autor>高亚舒</autor> 
          </book> 
        </books> 
      </Library> 
</Librarys>
我们可以非常清晰地看到xml的树形结构,现在就可以编写与之对应的java类了.以下是部分类代码片段:
public class Library {
    private int id;              
    private String name;
    private String address;
    LinkedList<Book> list_book ;
}
public class Book {
    private String name;
    private int price;
    private String autor;
}
//(为节省篇幅,get和set已省略...)

类设计好后,后面的工作就是对Pull的理解与使用了.现在简单介绍下Pull在生成Xml时需要用到的方法:
1. 创建Pull工厂对象:XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
2. 创建序列化工人对象(可理解xml生成器对象):XmlSerializer serializer = factory.newSerializer();
3. 设置输出流对象,注意这里建议使用Writer里的字符转换流对象,手动对文件的编码进行设置,否则默认采用工程的编码处理xml文件容易导致乱码的问题:Writer writer = (Writer) new OutputStreamWriter(new FileOutputStream(“yourxml”),”utf-8”);
4. 设置序列化工人的输出流: serializer.setOutput(writer);
5. 设置开始标签: serializer.startTag
6. 设置标签属性: serializer.attribute
7. 设置标签文本: serializer.text
7. 设置结尾标签: serializer.endTag

只要掌握套路,在生成过程中,我们按对象格式规范地写入xml文档中,其余基本都是小问题~由于我的代码注释很详细,所以废话不多说,下面直接展示代码:

    //把对象写入XML
    public static void writeXml(List<Library> list_library) throws Exception{

        //创建解析工厂对象
        XmlPullParserFactory factory = XmlPullParserFactory.newInstance();

        //从工厂中创建serializer对象
        XmlSerializer serializer = factory.newSerializer();

        //----定义字符流对象,建议采用转换流对字符进行utf-8编码设置
        Writer writer = (Writer) new OutputStreamWriter(new FileOutputStream("Library.xml"),"utf-8");

        //设置serializer的输出流
        serializer.setOutput(writer);

        //开始设置第一个标签:<Librarys>
        serializer.startTag(null, "Librarys");
        //<Librarys>节点下有数个<Library>节点,所以需要循环创建
        for(int i=0;i<list_library.size();i++)
        {
            Library library = list_library.get(i);

            //下面参照<Library>的树形结构
            serializer.startTag(null,"Library");

            serializer.attribute(null, "id", library.getId()+"");

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

            serializer.startTag(null,"address");
            serializer.text(library.getAddress());
            serializer.endTag(null, "address");

            //<Library>内存在一个books集合,便于管理所有book
            serializer.startTag(null,"books");

            //<books>节点下有数个<book>节点,开始循环创建
            List<Book> list_book = library.getList_book();
            for(int j=0;j<list_book.size();j++)
            {
                Book book = list_book.get(j);

                //下面参照<book>的树形结构
                serializer.startTag(null, "book");

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

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

                serializer.startTag(null,"author");
                serializer.text(book.getAutor());
                serializer.endTag(null,"author");

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

            //回去的时候别忘了设置endTag,若忘了请参照整个Xml的结构
            serializer.endTag(null, "books");

            serializer.endTag(null, "Library");

        }
        serializer.endTag(null, "Librarys");

        //----记得手动推送并关闭流对象,这个很重要
        writer.flush();
        writer.close();

        System.out.println("写入完成");
    }

检查文件,只要XML内容与最初的样板一致.这样一个方法就写好了.在使用的时候只需要传入Library的集合,代码就会动态帮我们生成所对应的xml文件.需要注意的是.我在文中直接抛出了异常,这是为了方便朋友们阅读.在实际开发中并不建议采取这种做法,更多的时候我们需要去捕获这个异常.
文档是创建好了,接下来我们需要反过来从文档中解析为Java对象.废话不多说,我们还是先了解一下解析XML文档要掌握的方法.
1. 创建Pull工厂对象:XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
2. 创建解析工人对象:XmlPullParser parser = factory.newPullParser();
3. 在读取时可以不使用转换流,因为已知XML编码为utf-8,可以使用默认编码设置.现在设置解析工人的输出流: parser.setInput(new FileInputStream(“youXml”),”UTF-8”);
4. 获取标签名: parser.getName
5. 获取标签内容: parser.getText
6. 获取标签属性名: parser.getAttributeName
7. 获取标签属性值: parser.getAttributeValue
8. 获取标签属性总数: parser.getAttributeCount
9. 获取本次事件类型: parser.getEventType
10. 开始下一次事件并获取事件类型: parser.next

简单解释一下事件类型: Pull解析器在解析时采用”事件驱动”的方式进行,每当Pull读到某种类型的事件,就可以由程序员在进行相应的处理.事件类型本身只是int数值类型,分别代表了:START_DOCUMENT(读取文档开始),START_TAG(读取到开始标签),END_TAG(读取到结尾标签),TEXT(读取到标签的内容),END_DOCUMENT(读取到文档末尾).由于事件类型本身只是int类型的数据,我们可以用switch来进行事件判断和处理.

现在我们在使用Pull解析XML文档时,过程就变得非常简单了,即:遇见一个标签->做标签该做的事情,然后周而复始,直到文件结束.不过有一点需要注意,由于Pull使用流的方式读取文档,整个框架中不存在节点的概念,如果涉及到节点嵌套且标签名重复的情况下,Pull解析本身无法提供这种辨识的功能.所以需要我们进行手动处理.好了废话不多说,同样直接展示代码:

    //从xml中读取对象
    public static void ReadXml() throws XmlPullParserException, IOException
    {
        LinkedList<Book> list_book = null;      //书的集合
        LinkedList<Library> list_library =null; //图书馆集合

        //创建解析工厂对象
        XmlPullParserFactory factory  = XmlPullParserFactory.newInstance();

        //从工厂中创建一个parser用于解析数据
        XmlPullParser parser = factory.newPullParser();

        //为parser设置读入字符流
        parser.setInput(new FileInputStream("Library.xml"),"UTF-8");

        Library library = null;     //图书馆
        Book book = null;           //书
        String tag_name = null;     //标签
        String parents = null;      //父标签
        int event_type= parser.getEventType();  //当前事件类型
        while(event_type != XmlPullParser.END_DOCUMENT)
        {
            switch(event_type)
            {
            case XmlPullParser.START_DOCUMENT:
                break;

            case XmlPullParser.START_TAG:
                tag_name = parser.getName();        //获取标签名

                if(tag_name.equals("Librarys"))     //如果当前标签为Librarys,说明可以创建图书馆集合了      
                {   
                    list_library = new LinkedList<Library>();
                }
                if(tag_name.equals("Library"))      //如果当前标签为Library,说明可以创建图书馆对象了.ps:图书馆存在一个属性id,因此需要额外获取一下该属性  
                {   
                    library = new Library();
                    parents = "Library";        

                    for(int i=0;i<parser.getAttributeCount();i++)   //Library标签比较头疼,因为含有属性,需要单独处理下属性
                    {
                        if(parser.getAttributeName(i).equals("id"))
                            library.setId(Integer.parseInt(parser.getAttributeValue(i)));
                    }
                }
                if(tag_name.equals("books"))        //如果当前标签为books,说明可以创建书的集合了
                {   
                    list_book = new LinkedList<Book>();         
                }
                if(tag_name.equals("book"))         //如果当前标签为book,说明可以创建书本对象了
                {
                    book = new Book();
                    parents = "book";
                }
                break;

            case XmlPullParser.END_TAG:         
                tag_name = "";      //----对tag进行清零处理,防止末尾行读取空格内容

                if(parser.getName().equals("book"))     //看到book的结尾标签时,说明可以把书添加进books集合了
                {   
                    list_book.addLast(book);
                }
                if(parser.getName().equals("books"))    //看到books的结尾标签时,说明可以把书的集合放进Library了
                {   
                    library.setList_book(list_book);
                }
                if(parser.getName().equals("Library"))  //看到Library的结尾标签时,说明可以把图书馆放进Librarys集合了
                {   
                    list_library.addLast(library);
                }
                break;

            case XmlPullParser.TEXT:
                String data = parser.getText();         //获取标签内容

                if(parents.equals("Library"))           //当父标签为Library时
                {   
                    if(tag_name.equals("name"))         //对name标签进行取值并赋值
                        library.setName(data);
                    else    if(tag_name.equals("address"))//对address标签进行取值并赋值
                        library.setAddress(data);
                }
                else    if(parents.equals("book"))      //当父标签为book时
                {
                    if(tag_name.equals("name"))             //对name标签进行取值并赋值
                        book.setName(data);
                    else    if(tag_name.equals("price"))    //对price标签进行取值并赋值
                        book.setPrice(Integer.parseInt(data));
                    else    if(tag_name.equals("author"))   //对author标签进行取值并赋值
                        book.setAutor(data);    
                }
                break;
            }
            event_type = parser.next();
        }

        for(Library l : list_library)
        {
            System.out.println(l);  //这里我为了测试所以直接打印结果了.大家可以在这里返回集合
        }
    }
最后的结果
Library [id=9741, name=北京航空航天大学图书馆, address=河南广场62号-5-4, list_book=[Book [name=野狼历险记, price=81, autor=萧保], Book [name=悠悠历险记, price=29, autor=童河谦], Book [name=虎虎历险记, price=24, autor=贾翠桂], Book [name=李图图历险记, price=94, autor=姜岩], Book [name=登登历险记, price=41, autor=夏慧]]]
Library [id=92549, name=中国海洋大学图书馆, address=文阳街107号-12-6, list_book=[Book [name=咪妹历险记, price=12, autor=黄英], Book [name=咪妹历险记, price=90, autor=蓬璧], Book [name=班尼历险记, price=22, autor=韩士], Book [name=大奔历险记, price=34, autor=戴雪], Book [name=妞妞历险记, price=78, autor=狄琦荔]]]

这样我们使用Pull完成了从对象到XML再从XML到对象的完整过程.文中需要注意的地方我使用了”//—-“的形式进行了标注,希望大家多留意.不过我还要再次强调的一点是:使用这种逻辑结构即系XML文档时,虽然结构简单风格唯美.但一定要在EndTAG的时候对tag进行清空字符串处理!清空字符串!清空字符串!重要的事情说三次,请切记

如果到了这里以后您突然发现代码的适应性太局限,该方法仅对本Library对象可用,但对其他对象就不适用了.没错,毕竟这只是Pull解析的基础教程.如果您想用Pull生成或解析任意对象,那么恭喜您,从思想层面上您已经跨入Java的无底深渊了.哈哈~开个玩笑.在下一篇博客,我将教朋友们怎样使用Java的反射思想动态生成任意类的xml文件 ~~~

  • 最后再Ps一下:此篇教程仅仅为初学者提供,大鸟勿喷,如有不足我会努力改正~~~xiexie

猜你喜欢

转载自blog.csdn.net/u014370586/article/details/53426550