XML的几种解析方式,及其代码实现

常用的几种解析XML的技术!

A:DOM:在内存中构建一颗倒挂的树,通过对内存中的节点进行操作从而解析XML

缺点:由于需要根据XML文档构造倒挂的树,所以当XML文档比较大时,非常耗内存。有造成内存溢出的危险。不适合移动设备的开发.

B:SAX:基于事件驱动的方式解析XML(推模式PUSH)

C:JDOM:对DOM模型的简化,专门针对Java语言解析XML而设计的

D:DOM4J:融入了XPath语法等,是目前解析XML功能最强大的一门技术

E:PULL:基于事件驱动的方式解析XML.(拉模式(PULL))!


在xml解析过程中有一个共性:xml开始标签->xml文本内容->xml结束标签->空白文本内容->下一个xml开始标签


(1)DOM解析

     //声明books集合用于存每个book对象

List<Book> books=new  ArrayList<Book>();

       //1.通过调用DocumentBuilderFactory的静态方法newInstance()得到DOM解析器工厂对象

        DocumentBuilderFactory documentBuilderFactory=DocumentBuilderFactory.newInstance();

            //2.通过DOM解析器工厂对象得到DOM解析器对象

            DocumentBuilderdocumentBuilder= documentBuilderFactory.newDocumentBuilder();

           //3.以流的形式指定要解析的XML文件并返回文档对象

            InputStreaminputStream=Thread.currentThread().getContextClassLoader().getResourceAsStream("books.xml");

            Document document=documentBuilder.parse(inputStream);     

            //4.通过文档对象得到根节点对应的元素对象

            Elementroot=document.getDocumentElement();

            //5.根据节点的名称得到节点的集合

            NodeListbook_nodeList=root.getElementsByTagName("book");

            //6.返回节点的个数

            int len=book_nodeList.getLength();

            //System.out.println("len="+len+",book_nodeList="+book_nodeList);

            //7.遍历节点并获取需要的数据

            for(inti=0;i<len;i++){

                //根据索引获取指定的节点对象

                Node node_book=book_nodeList.item(i);

                //将节点向下转型成元素,为什么要转?因为只有元素对象采用根据属性名获取属性值的方法Stringvalue=getAttribute(name);

                Element element_book=(Element) node_book;

               //获取此节点元素的属性值

                String isbn=element_book.getAttribute("isbn");

               //这里获得的element_book其实是一个集合对象,根据getElementsByTagName方法获得的标签元素也是集合,但因为只有一个集合元素,所以直接item(0),然后获取其标签文本内容,getTextContent();

                String name=element_book.getElementsByTagName("name").item(0).getTextContent();

                String author=element_book.getElementsByTagName("author").item(0).getTextContent();

                String price=element_book.getElementsByTagName("price").item(0).getTextContent();

                String publish=element_book.getElementsByTagName("publish").item(0).getTextContent();

                //将遍历得到的每组元素里面的小元素值通过构造函数存放到book对象中去

                Book book=new Book(isbn,name,author,price,publish);

                //将每个对象存放到Arraylist集合当中去

                books.add(book);

   (2)SAX解析

    //1.通过调用SAXParserFactory工厂的静态方法newInstance()得到SAX解析器工厂对象

        SAXParserFactorysaxParserFactory=SAXParserFactory.newInstance();

            //2.通过SAX解析器工厂对象得到SAX解析器对象

             SAXParsersaxParser=saxParserFactory.newSAXParser();

             //3.指定要解析的Xml文件路径及其解析器对象

             InputStreaminputStream=Thread.currentThread().getContextClassLoader().getResourceAsStream("books.xml");

             saxParser.parse(inputStream, new MyHandler());

           //try catch省略

4.编写处理器类中相关的方法,必须继承DefaultHandler或者实现ContentHandler接口,建议继承DefaultHandler,并重写其中的常用方法

         startDocument():开始解析Xml文档时自动调用的方法

         startElement():遇到开始标签时自动调用的方法

         characters():遇到文本元素时自动调用的方法

         endElement():遇到结束标签时自动调用的方法

         endDocument():解析Xml结束后自动调用的方法


    //自定义SAX解析器类必须继承DefaultHandler或者实现ContentHandler接口,建议继承DefaultHandler

    private static classMyHandler extends DefaultHandler{

            // 声明存储Book对象的数据源

        private List<Book> books;

            // 声明Book对象

        private Book book;

           //定义用来存储当前正在解析的节点的前面的标签名

        private String parent;

           // 当收到一个开始解析Xml的通知的时候自动调用的方法,这个方法在整个Xml解析过程中只调用一次

        @Override

        public void startDocument()throws SAXException{

            books=newArrayList<Book>();  //当开始解析xml文档时开始声明一个ArrayList()集合 用于存放每个书的信息的对象

            System.out.println("=======startDocument()=========");

        }

        //当遇到Xml的开始标签时自动调用的方法,调用多少次取决于指定的Xml文件中有多少个开始标签

         //@param qName是我们解析Xml节点的标签名

        @Override

        public void startElement(String uri, StringlocalName, String qName,

                Attributes attributes) throws SAXException {

            this.parent=qName;//在遍历到开始标签时将此标签名用parent记录下来

            if("book".equals(qName)){

                book=new Book();//如果遍历标签时遍历到了每组数据的开始标签则new一个对象

                //根据属性名获取属性值

                Stringisbn=attributes.getValue("isbn");

                book.setIsbn(isbn);

            }

            System.out.println("=====startElement(Stringuri="+uri+", String localName="+localName+", StringqName="+qName+",Attributesattributes="+attributes+")========");

        }

         //当遇到文本元素时自动调用的方法

        @Override

        public void characters(char[] ch, int start,int length)

                throws SAXException {

            Stringdata=new String(ch,start,length);

          //当遍历到文本时它前面为开始标签名等于一下内容时,将文本内容存放到对应的对象中去

            if("name".equals(parent)){

                this.book.setName(data);

            }elseif("author".equals(this.parent)){

                this.book.setAuthor(data);

            }elseif("price".equals(parent)){

                this.book.setPrice(data);

            }elseif("publish".equals(parent)){

                this.book.setPublish(data);

            }

            System.out.println("=====characters(char[]ch, int start, int length).data="+data);

        }

      // 当前遇到Xml的结束标签时自动调用的方法,调用多少次取决于当前Xml文件中有多少个结束标签

        @Override

        public void endElement(String uri, StringlocalName, String qName)

                throws SAXException {

            //在遇到结束标签时必须将parent的值赋为null,否则会产生空白(空格,回车,换行)覆盖之前文本的情况,因为结束标签和开始标签之间的文本也会调用方法,如果没parent没置空,则此时意味着空白文本前世开始标签,则会覆盖正确的文本

            this.parent=null;

            if("book".equals(qName)){

                this.books.add(book);//如果扫描结束标签时扫到这组的结束标签,则意味着这组结束,将这组的信息以对象的方式存放到 集合当中去

            }

            System.out.println("====endElement(Stringuri="+uri+", String localName="+localName+", StringqName="+qName+")=====");

        }

           //当收到一个当前文件解析完毕的通知后自动调用的方法,这个方法在整个Xml解析过程中也只调用一次

        @Override

        public void endDocument() throwsSAXException {

            System.out.println("books="+this.books);//结束解析后输出集合中的信息

            System.out.println("======endDocument()====");

        }

    }

}

(3)pull解析

     在使用pull解析之前在java项目中需要导入第三方jar包,Android不需要。


* PULL解析:拉模式的解析方式

 * 实现步骤:

 * 1.得到PUll解析器工厂对象

 *     XmlPullParserFactoryxmlPullParserFactory=XmlPullParserFactory.newInstance();

  2.通过工厂对象得到PULL解析器对象

 *     XmlPullParser xmlPullParser=xmlPullParserFactory.newPullParser();

 * 3.指定要解析的Xml文件以流的形式,同时指定编码表

 *     InputStreaminputStream=Thread.currentThread().getContextClassLoader().getResourceAsStream("books.xml");

        xmlPullParser.setInput(inputStream,"UTF-8");

    4.得到当前的事件值

        inteventType=xmlPullParser.getEventType();

    5.循环推动事件流解析XML中的数据

        while(eventType!=XmlPullParser.END_DOCUMENT){//当没遍历到文档结束之前依次遍历

                switch(eventType) {

                    case XmlPullParser.START_DOCUMENT://当文档开始遍历时声明集合对象

                        books=newArrayList<Book>();

                        break;

                    case XmlPullParser.START_TAG:  //遍历开始标签

                        StringstartTag=xmlPullParser.getName();//得到当前正在解析的标签名

                        if("book".equals(startTag)){

                            book=new Book();

                            String isbn=xmlPullParser.getAttributeValue(null,"isbn");

                            book.setIsbn(isbn);

                        }elseif("name".equals(startTag)){

                            //得到当前标签下的文本内容,此时事件流会继续向后推动

                            String name=xmlPullParser.nextText();

                            book.setName(name);

                        }elseif("author".equals(startTag)){

                            String author=xmlPullParser.nextText();

                            book.setAuthor(author);

                        }elseif("price".equals(startTag)){

                            String price=xmlPullParser.nextText();

                            book.setPrice(price);

                        }elseif("publish".equals(startTag)){

                            String publish=xmlPullParser.nextText();

                            book.setPublish(publish);

                            books.add(book);

                           

                        }

                        System.out.println("===XmlPullParser.START_TAG中的startTag="+startTag);

                        break;

                    case XmlPullParser.END_TAG://遍历到结束标签

                        StringendTag=xmlPullParser.getName();//得到当前正在解析的标签名

                        System.out.println("===XmlPullParser.END_TAG中的endTag="+endTag);

                        break;

                    case XmlPullParser.TEXT://遍历到文本内容

                        System.out.println("===XmlPullParser.TEXT=====");

                        break;

                    default:

                        break;

                }

                //将事件流继续向后推动

              //这句话是pull解析所必须的,因为pull解析是拉着进行的,没有这句话则会进入死循环,初学者注意

                eventType=xmlPullParser.next();

            }



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值