加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

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

发布时间:2020-12-16 06:08:42 所属栏目:百科 来源:网络整理
导读:常用的几种解析XML的技术! A:DOM:在内存中构建一颗倒挂的树,通过对内存中的节点进行操作从而解析XML 缺点:由于需要根据XML文档构造倒挂的树,所以当XML文档比较大时,非常耗内存。有造成内存溢出的危险。不适合移动设备的开发. B:SAX:基于事件驱动的方式

常用的几种解析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=newArrayList<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=newBook(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 length).data="+data);

}

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

@Override

public void endElement(String uri,String qName)

throws SAXException {

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

this.parent=null;

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

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

}

System.out.println("====endElement(Stringuri="+uri+",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();

}

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读