XML的三种解析文档格式.docx

上传人:b****8 文档编号:22949513 上传时间:2023-02-06 格式:DOCX 页数:17 大小:182.53KB
下载 相关 举报
XML的三种解析文档格式.docx_第1页
第1页 / 共17页
XML的三种解析文档格式.docx_第2页
第2页 / 共17页
XML的三种解析文档格式.docx_第3页
第3页 / 共17页
XML的三种解析文档格式.docx_第4页
第4页 / 共17页
XML的三种解析文档格式.docx_第5页
第5页 / 共17页
点击查看更多>>
下载资源
资源描述

XML的三种解析文档格式.docx

《XML的三种解析文档格式.docx》由会员分享,可在线阅读,更多相关《XML的三种解析文档格式.docx(17页珍藏版)》请在冰豆网上搜索。

XML的三种解析文档格式.docx

该类是Apache的Xerces中的DOM解析器类,可直接解析XML文件。

下面是DOM的解析流程:

第二种方式:

SAX解析器:

SAX(SimpleAPIforXML)解析器是一种基于事件的解析器,事件驱动的流式解析方式是,从文件的开始顺序解析到文档的结束,不可暂停或倒退。

它的核心是事件处理模式,主要是围绕着事件源以及事件处理器来工作的。

当事件源产生事件后,调用事件处理器相应的处理方法,一个事件就可以得到处理。

在事件源调用事件处理器中特定方法的时候,还要传递给事件处理器相应事件的状态信息,这样事件处理器才能够根据提供的事件信息来决定自己的行为。

SAX解析器的优点是解析速度快,占用内存少。

非常适合在Android移动设备中使用。

SAX的工作原理:

SAX的工作原理简单地说就是对文档进行顺序扫描,当扫描到文档(document)开始与结束、元素(element)开始与结束、文档(document)结束等地方时通知事件处理函数,由事件处理函数做相应动作,然后继续同样的扫描,直至文档结束。

在SAX接口中,事件源是org.xml.sax包中的XMLReader,它通过parser()方法来解析XML文档,并产生事件。

事件处理器是org.xml.sax包中ContentHander、DTDHander、ErrorHandler,以及EntityResolver这4个接口。

XMLReader通过相应事件处理器注册方法setXXXX()来完成的与ContentHander、DTDHander、ErrorHandler,以及EntityResolver这4个接口的连接。

常用的SAX接口和类:

Attrbutes:

用于得到属性的个数、名字和值。

ContentHandler:

定义与文档本身关联的事件(例如,开始和结束标记)。

大多数应用程序都注册这些事件。

DTDHandler:

定义与DTD关联的事件。

它没有定义足够的事件来完整地报告DTD。

如果需要对DTD进行语法分析,请使用可选的DeclHandler。

DeclHandler是SAX的扩展。

不是所有的语法分析器都支持它。

EntityResolver:

定义与装入实体关联的事件。

只有少数几个应用程序注册这些事件。

ErrorHandler:

定义错误事件。

许多应用程序注册这些事件以便用它们自己的方式报错。

DefaultHandler:

它提供了这些接LI的缺省实现。

在大多数情况下,为应用程序扩展DefaultHandler并覆盖相关的方法要比直接实现一个接口更容易。

详见下表:

可知,我们需要XmlReader以及DefaultHandler来配合解析xml。

下面是SAX的解析流程:

第三种方式:

PULL解析器:

Android并未提供对JavaStAXAPI的支持。

但是,Android附带了一个pull解析器,其工作方式类似于StAX。

它允许用户的应用程序代码从解析器中获取事件,这与SAX解析器自动将事件推入处理程序相反。

PULL解析器的运行方式和SAX类似,都是基于事件的模式。

不同的是,在PULL解析过程中返回的是数字,且我们需要自己获取产生的事件然后做相应的操作,而不像SAX那样由处理器触发一种事件的方法,执行我们的代码。

读取到xml的声明返回START_DOCUMENT;

读取到xml的结束返回END_DOCUMENT;

读取到xml的开始标签返回START_TAG

读取到xml的结束标签返回END_TAG

读取到xml的文本返回TEXT

PULL解析器小巧轻便,解析速度快,简单易用,非常适合在Android移动设备中使用,Android系统内部在解析各种XML时也是用PULL解析器,Android官方推荐开发者们使用Pull解析技术。

Pull解析技术是第三方开发的开源技术,它同样可以应用于JavaSE开发。

PULL的工作原理:

XMLpull提供了开始元素和结束元素。

当某个元素开始时,我们可以调用parser.nextText从XML文档中提取所有字符数据。

当解释到一个文档结束时,自动生成EndDocument事件。

常用的XMLpull的接口和类:

XmlPullParser:

XMLpull解析器是一个在XMLPULLVlAP1中提供了定义解析功能的接口。

XmlSerializer:

它是一个接口,定义了XML信息集的序列。

XmlPullParserFactory:

这个类用于在XMPULLV1API中创建XMLPull解析器。

XmlPullParserException:

抛出单一的XMLpull解析器相关的错误。

PULL的解析流程如下:

[附加]第四种方式:

Android.util.Xml类

在AndroidAPI中,另外提供了Android.util.Xml类,同样可以解析XML文件,使用方法类似SAX,也都需编写Handler来处理XML的解析,但是在使用上却比SAX来得简单,如下所示:

以android.util.XML实现XML解析,

MyHandlermyHandler=newMyHandler0;

android.util.Xm1.parse(ur1.openC0nnection().getlnputStream0,Xm1.Encoding.UTF-8,myHandler);

下面是一个参考文档river.xml,放在assets目录.如下:

<

?

xmlversion="

1.0"

encoding="

utf-8"

?

>

rivers>

rivername="

灵渠"

length="

605"

introduction>

灵渠在广西壮族自治区兴安县境内,是世界上最古老的运河之一,有着“世界古代水利建筑明珠”的美誉。

灵渠古称秦凿渠、零渠、陡河、兴安运河,于公元前214年凿成通航,距今已2217年,仍然发挥着功用。

/introduction>

imageurl>

/imageurl>

/river>

胶莱运河"

200"

胶莱运河南起黄海灵山海口,北抵渤海三山岛,流经现胶南、胶州、平度、高密、昌邑和莱州等,全长200公里,流域面积达5400平方公里,南北贯穿山东半岛,沟通黄渤两海。

胶莱运河自平度姚家村东的分水岭南北分流。

南流由麻湾口入胶州湾,为南胶莱河,长30公里。

北流由海仓口入莱州湾,为北胶莱河,长100余公里。

苏北灌溉总渠"

168"

位于淮河下游江苏省北部,西起洪泽湖边的高良涧,流经洪泽,青浦、淮安,阜宁、射阳,滨海等六县(区),东至扁担港口入海的大型人工河道。

全长168km。

/rivers>

采用DOM解析时具体处理步骤是:

1首先利用DocumentBuilderFactory创建一个DocumentBuilderFactory实例

2然后利用DocumentBuilderFactory创建DocumentBuilder

3然后加载XML文档(Document),

4然后获取文档的根结点(Element),

5然后获取根结点中所有子节点的列表(NodeList),

6然后使用再获取子节点列表中的需要读取的结点。

当然我们观察节点,我需要用一个River对象来保存数据,抽象出River类

publicclassRiverimplementsSerializable{

privatestaticfinallongserialVersionUID=1L;

privateStringname;

publicStringgetName(){

returnname;

}

publicvoidsetName(Stringname){

this.name=name;

publicintgetLength(){

returnlength;

publicvoidsetLength(intlength){

this.length=length;

publicStringgetIntroduction(){

returnintroduction;

publicvoidsetIntroduction(Stringintroduction){

this.introduction=introduction;

publicStringgetImageurl(){

returnimageurl;

publicvoidsetImageurl(Stringimageurl){

this.imageurl=imageurl;

privateintlength;

privateStringintroduction;

privateStringimageurl;

下面我们就开始读取xml文档对象,并添加进List中:

代码如下:

我们这里是使用assets中的river.xml文件,那么就需要读取这个xml文件,返回输入流。

读取方法为:

inputStream=this.context.getResources().getAssets().open(fileName);

参数是xml文件路径,当然默认的是assets目录为根目录。

然后可以用DocumentBuilder对象的parse方法解析输入流,并返回document对象,然后再遍历doument对象的节点属性。

//获取全部河流数据

/**

*参数fileName:

为xml文档路径

*/

publicList<

River>

getRiversFromXml(StringfileName){

List<

rivers=newArrayList<

();

DocumentBuilderFactoryfactory=null;

DocumentBuilderbuilder=null;

Documentdocument=null;

InputStreaminputStream=null;

//首先找到xml文件

factory=DocumentBuilderFactory.newInstance();

try{

//找到xml,并加载文档

builder=factory.newDocumentBuilder();

document=builder.parse(inputStream);

//找到根Element

Elementroot=document.getDocumentElement();

NodeListnodes=root.getElementsByTagName(RIVER);

//遍历根节点所有子节点,rivers下所有river

Riverriver=null;

for(inti=0;

i<

nodes.getLength();

i++){

river=newRiver();

//获取river元素节点

ElementriverElement=(Element)(nodes.item(i));

//获取river中name属性值

river.setName(riverElement.getAttribute(NAME));

river.setLength(Integer.parseInt(riverElement.getAttribute(LENGTH)));

//获取river下introduction标签

Elementintroduction=(Element)riverElement.getElementsByTagName(INTRODUCTION).item(0);

river.setIntroduction(introduction.getFirstChild().getNodeValue());

ElementimageUrl=(Element)riverElement.getElementsByTagName(IMAGEURL).item(0);

river.setImageurl(imageUrl.getFirstChild().getNodeValue());

rivers.add(river);

}catch(IOExceptione){

e.printStackTrace();

}catch(SAXExceptione){

catch(ParserConfigurationExceptione){

}finally{

inputStream.close();

}catch(IOExceptione){

returnrivers;

在这里添加到List中,然后我们使用ListView将他们显示出来。

如图所示:

采用SAX解析时具体处理步骤是:

1创建SAXParserFactory对象

2根据SAXParserFactory.newSAXParser()方法返回一个SAXParser解析器

3根据SAXParser解析器获取事件源对象XMLReader

4实例化一个DefaultHandler对象

5连接事件源对象XMLReader到事件处理类DefaultHandler中

6调用XMLReader的parse方法从输入源中获取到的xml数据

7通过DefaultHandler返回我们需要的数据集合。

parse(StringxmlPath){

rivers=null;

SAXParserFactoryfactory=SAXParserFactory.newInstance();

SAXParserparser=factory.newSAXParser();

//获取事件源

XMLReaderxmlReader=parser.getXMLReader();

//设置处理器

RiverHandlerhandler=newRiverHandler();

xmlReader.setContentHandler(handler);

//解析xml文档

//xmlReader.parse(newInputSource(newURL(xmlPath).openStream()));

xmlReader.parse(newInputSource(this.context.getAssets().open(xmlPath)));

rivers=handler.getRivers();

}catch(ParserConfigurationExceptione){

//TODOAuto-generatedcatchblock

}catch(IOExceptione){

重点在于DefaultHandler对象中对每一个元素节点,属性,文本内容,文档内容进行处理。

前面说过DefaultHandler是基于事件处理模型的,基本处理方式是:

当SAX解析器导航到文档开始标签时回调startDocument方法,导航到文档结束标签时回调endDocument方法。

当SAX解析器导航到元素开始标签时回调startElement方法,导航到其文本内容时回调characters方法,导航到标签结束时回调endElement方法。

根据以上的解释,我们可以得出以下处理xml文档逻辑:

1:

当导航到文档开始标签时,在回调函数startDocument中,可以不做处理,当然你可以验证下UTF-8等等。

2:

当导航到rivers开始标签时,在回调方法startElement中可以实例化一个集合用来存贮list,不过我们这里不用,因为在构造函数中已经实例化了。

3:

导航到river开始标签时,就说明需要实例化River对象了,当然river标签中还有name,length属性,因此实例化River后还必须取出属性值,attributes.getValue(NAME),同时赋予river对象中,同时添加为导航到的river标签添加一个boolean为真的标识,用来说明导航到了river元素。

4:

当然有river标签内还有子标签(节点),但是SAX解析器是不知道导航到什么标签的,它只懂得开始,结束而已。

那么如何让它认得我们的各个标签呢?

当然需要判断了,于是可以使用回调方法startElement中的参数StringlocalName,把我们的标签字符串与这个参数比较下,就可以了。

我们还必须让SAX知道,现在导航到的是某个标签,因此添加一个true属性让SAX解析器知道。

5:

它还会导航到文本内标签,(就是<

img>

/img>

里面的内容),回调方法characters,我们一般在这个方法中取出就是<

里面的内容,并保存。

6:

当然它是一定会导航到结束标签<

或者<

的,如果是<

标签,记得把river对象添加进list中。

如果是river中的子标签<

,就把前面设置标记导航到这个标签的boolean标记设置为false.按照以上实现思路,可以实现如下代码:

/**导航到开始标签触发**/

publicvoidstartElement(Stringuri,StringlocalName,StringqName,Attributesattributes){

StringtagName=localName.length()!

=0?

localName:

qName;

tagName=tagName.toLowerCase().trim();

//如果读取的是river标签开始,则实例化River

if(tagName.equals(RIVER)){

isRiver=true;

/**导航到river开始节点后**/

river.setName(attributes.getValue(NAME));

river.setLength(Integer.parseInt(attributes.getValue(LENGTH)));

//然后读取其他节点

if(isRiver){

if(tagName.equals(INTRODUCTION)){

xintroduction=true;

}elseif(tagName.equals(IMAGEURL)){

ximageurl=true;

}

/**导航到结束标签触发**/

publicvoidendElement(Stringuri,StringlocalName,StringqName){

//如果读取的是river标签结束,则把River添加进集合中

xintroduction=false;

ximageurl=false;

//这里是读取到节点内容时候回调

publicvoidcharacters(char[]ch,intstart,intlength){

//设置

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 求职职场 > 简历

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1