为什么SAX|DOM同时存在?
--------------------------------------------------------------------------------
SAX (Simple API for XML) 和 DOM (Document Object Model) 都是为了让程序员不用写一个解析器就可以访问他们的资料信息。通过利用XML 1.0格式保存信息,以及使用SAX或者DOM APIs你的程序可以使用任何解析器。这是因为使用他们所喜爱的语言开发解析器的开发者必须实现SAX和DOM APIs。 SAX和DOM APIs 对多种语言中都可以实现(Java, C++, Perl, Python, 其它...)。
所以SAX 和 DOM都是为了同样的目的而存在,这就是使用户可以利用任何编程语言访问存入XML文档中的信息(要有一个那种编程语言的解析器)。虽然他们在提供给你访问信息的方法上大不相同。
什么是DOM?
--------------------------------------------------------------------------------
DOM 可以让你以分层次对象模型来访问储存在XML文档中的信息。DOM生成一棵节点树(以XML文档的结构和信息为基础)你可以通过这棵树来访问你的信息。在XML文档中的文本信息转变成一组树的节点。
不管你的XML文档中的信息的类型 (不管是表格数据,或是一列items,或者只是文档), DOM在你创建一个XML文档的文档对象时创建一棵节点树。 DOM强迫你使用树状模型(就像 Swing TreeModel)去访问你的XML文档中的信息。这种模式确实不错因为XML原本就是分层次的。这也是DOM为什么可以把你的信息放到一棵树中的原因(即使信息是表格式的或者简单的列表????这里不知道该怎么翻原文是:even if the information is actually tabular or a simple list??????)。
因为在DOM中,每一个元素节点实际上都有一系列的其他节点作为它的孩子。这些孩子节点可以包含文本值或者是其他元素节点。乍看起来,通过遍历访问一个元素的所有孩子节点来访问这个节点的值是没有必要的(举例来说:节点 "<name> Nazmul </name>", Nazmul是值)。如果每个元素只有值的话,这确实是没有必要的。但是,元素可能含有文本数据或者其他元素;这是你要在DOM中做额外的工作来获取元素节点值的原因。 通常当你的文档中只有纯数据时,把所有的数据压成一个“块“放到字串中并让DOM把那个字串当成某个特定元素节点的值返回是适当的。这种方式并不适合如果在你的XML文档中的数据是个文档(比如像WORD文档或者FRAMEMAKER文档) 在文档中,元素的顺序是非常重要的。对于纯数据(像一个数据库表)元素的顺序是不要紧的。 之所以DOM保持从XML文档中读出的元素的顺序,因为它把所有的事物都当成文档来处理。 文档对像模型的叫法由此而来。
如果你计划用DOM做为JAVA对象模型用于你存储在XML文档中的信息,那么你不需要考虑SAX。可是如果你发现DOM不是一个可以用于处理XML文档信息的好的对象模式,那么你可能想看看SAX了。在一些必须使用自定义对象模型的案例中使用SAX是非常普遍的。说一句让事情看来有些糊涂的话,你也可以在DOM的基础之上创建自己的对象模式。面向对象真是个好东东。
什么是SAX?
--------------------------------------------------------------------------------
SAX让你访问储存在XML文档中的信息,不是通过节点树,而是一系列的事件。你会问,这有什么益处?回答是,SAX选择不在XML文档上创建JAVA对象模型(像DOM做的那样)。 这样使得SAX更快, 同时使下面所述成为必要:
创立你自己的自定义对像模型
创建一个监听SAX事件的类同时创建你自己的对象模型
注意这些步骤对DOM而言是不必要的,因为DOM已经为你创建了一个对象模型(将你的信息用一棵节点树表示)。
在使用DOM的情况下,解析器做了绝大多数事情, 读入XML文档, 在这基础之上创建JAVA对象模型,然后给你一个对这个对象的引用(一个 Document对象),因而你可以操作使用它。SAX被叫做Simple API for XML不是没有原因的, 她真的很简单。 SAX没有期待解析器去做这么多工作,所有SAX 要求的是解析器应该读入XML文档,同时根据所遇到的XML文档的标签发出一系列事件。你要自己写一个XML文档处理器类(XML document handler class)来处理这些事件,这意味着使所有标签事件有意义还有用你自己的对象模型创建对象。所以你要完成:
控制所有XML文档信息的自定义对象模型(或者源文档在这里的写法从来没有见过,或者怀疑源文档在这里有排版错误,先这么翻了)
一个监听SAX事件(事件由SAX解析器读取你的XML文档时产生)的文档处理器,还有解释这些事件创建你自定义对象模型中的对象
如果你的对象模型简单的话那么SAX在运行时会非常快。在这种情况下,它会比DOM快,因为它忽略了为你的信息创建一个树形对象模型的过程。从另一方面来说,你必须写一个SAX 文档处理器来解释所有的SAX事件(这会是一件很繁重的工作)。
什么类型的SAX事件被SAX解析器抛出了哪? 这些事件实际上是非常简单的。SAX会对每一个开始标签抛出事件,对每一个结束标签也是如此。它对#PCDATA和 CDATA 部分同样抛出事件。你的文档处理器 (对这些事件的监听器)要解释这些事件同时还要在他们基础之上创建你自定义的对象模型。 你的文档处理器必须对这些事件做出解释,同时这些事件发生的顺序是非常重要的。SAX同时也对processing instructions, DTDs, comments, 抛出事件. 但是它们在概念上是一样的, 你的解析器要解释这些事件(还有这些事件的发生顺序)以及使他们有意义。
什么时候使用DOM
--------------------------------------------------------------------------------
如果你的XML文档包含文档数据(例如, Framemaker documents stored in XML format), 那么DOM就是你的解决方案的最自然选择。如果你要创建一些类似于文档信息管理的系统,那么你不得不处理大量的文档数据。Datachannel RIO 产品就是这么一个例子,它可以索引和组织各种类型文档资源中的信息(例如Word和Excel 文件)。在这种情况下,DOM是非常合适程序去访问存贮在这些文档中的信息的。
然而,如果你主要处理的是结构化的数据(在XML中的序列化的JAVA对象the equivalent of serialized Java objects in XML),DOM不是最好的选择。那就是SAX会比较合适的地方。
什么时候使用SAX
--------------------------------------------------------------------------------
如果在你XML文档中的信息是机器易读的(和机器生成的)数据,那么SAX是让你可以访问这些信息的合适的API。机器易读和生成的数据类型包含像下面这些东东:
存成XML格式的Java对象属性
用一些以文本为基础的查询语句(SQL, XQL, OQL)表示的查询
由查询生成的结果集(这也许包含关系型数据库表中的数据编码成XML).
这么看来机器生成的数据是你一般要在java中生成数据结构和类的信息。一个简单的例子是包含个人信息的地址簿,在上图所示。这个地址簿xml文件不像字处理器文档,它是一个包含已经被编码成文本的纯数据的XML文档。
当你的数据是这种样式,你要创建你自己的数据结构和类(对象模型)来管理操作以及持续保存这些数据。SAX容许你快速创建一个可以生成你的对象模型实例的处理器类。一个实例是:一个SAX文档处理器。它完成的工作有读入包含我的地址薄信息的XML文档,创建一个可以访问到这些信息的AddressBook类。SAX指南告诉你该怎么做到这些。这个地址薄XML文档包含person元素,person元素中有name和email元素。我的AddressBook对象模型包括下面的类:
AddressBook 类,Person对象的容器
Person 类,String 型的name和email的容器
这样我的“SAX 地址簿文档处理器”可以把person元素转变成Person对象了,然后把它们都存入AddressBook对象。这个文档处理器将name和email元素转变为String对象。
结论
--------------------------------------------------------------------------------
你写的SAX文档处理器(SAX document handler)做了将元素映射为对象的工作。如果你的信息被结构化成可以容易创建这样的映射,你应该使用SAX API。从另一方面来说,如果你的数据更适宜用树来表示那么你应该使用DOM。
[020401050]DOM与ASP的接口问题?
[原作者:cmy8132]
我做的一个小问题是知识查询与疑难问题系统,用的是asp和xml做的,其中的查询模块如下实现,如果用C,C++如何实现?
<html>t="text/html; charset=gb2312">
<meta name="GENERATOR" content="Microsoft FrontPage 4.0">
<meta name="ProgId" content="FrontPage.Editor.Document">
<title>查询结果</title>
<script language="javascript" type="text/javascript">
<!--
function MM_reloadPage(init) { //reloads the window if Nav4 resized
if (init==true) with (navigator) {if ((appName=="Netscape")&&(parseInt(appVersion)==4)) {
document.MM_pgW=innerWidth; document.MM_pgH=innerHeight; onresize=MM_reloadPage; }}
else if (innerWidth!=document.MM_pgW || innerHeight!=document.MM_pgH) location.reload();
}
MM_reloadPage(true);
//-->
</script>
</head>
<body bgcolor="#000000">
<div align="center">
<center>
<table border="0" width="611" cellspacing="0" cellpadding="0" height="528" background="images/i-3-1.gif">
<!--DWLayoutTable-->
<tr>
<td width="609" height="539" valign="top" background="images/t-02.gif">
<div align="right">
<table border="0" width="91%" cellspacing="5" cellpadding="5" height="477">
<!--DWLayoutTable-->
<tr>
<td width="1" height="80"></td>
<td width="100%"> <p align="center"><font color="#FF3366" size="4" face="仿宋_GB2312"><em><strong>我
们一直在努力</strong></em></font></td>
</tr>
<tr bgcolor="#006666">
<td height="61" colspan="2" valign="top"><div align="center"><font color="#00FF00" size="6"><strong>问题答案是</strong></font></div></td>
</tr>
<tr>
<td height="349" colspan="2" valign="middle" bgcolor="#006460">
<div align="left">
<form name="form1" method="post" action="">
<p>
<%
question=request.form("std_question")
question=trim(question)
length=len(question)
question=left(question,length-4)
keywords=SPLIT(question,"的")
keyword_num=ubound(keywords)+1
Set DomXML=Server.CreateObject("MSXML.DOMDocument")
DomXML.Load "d:/知识查询与疑难问题系统/ds.XML"
Set root=DomXML.documentElement
set childNodes=root.selectNodes("//"&keywords(0)) '查找符合第一个关键字的所有节点
if childNodes.length=0 then response.Write "<font color='#FF3366'>"&"对不起,找不到你要的问题的答案!" &"</font>"
dim stack()
redim stack(100,1)
top=0
for i=0 to childNodes.length-1
set child=childNodes.item(i)
set stack(top,0)=child
stack(top,1)=0
top=top+1
next
answer_order=1
while top>0
top=top-1
set parent=stack(top,0)
key_i=stack(top,1)
if key_i+1=keyword_num then '关键字匹配完毕
answer=question
answer=CStr(answer_order)&"."&answer
answer_order=answer_order+1
set answerNodes=parent.childNodes
if answerNodes.length>1 then
answer=answer&"可分为:"
else
answer=answer&"是:"
end if
for m=0 to answerNodes.length-2
set child=answerNodes.item(m)
if child.nodeType=1 or child.nodetype=2 then 'Current node is element node
answer=answer&child.nodename&"、"
elseif child.nodeType=3 or child.nodeType=4 then
answer=answer&"
"&child.text&"
"
end if
next
set child=answerNodes.item(m)
if m>0 then
if child.nodeType=1 then
answer=answer&"和"&child.nodeName&"。<hr>"
elseif child.nodeType=3 or child.nodeType=4 then
answer=answer&"和"&child.text&"。<hr>"
end if
else
if child.nodeType=1 then
answer=answer&child.nodeName&"。<hr>"
elseif child.nodeType=3 or child.nodeType=4 then
answer=answer&child.text&"。<hr>"
end if
end if
response.Write "<font color='#FF3366'>"&answer&"</font>"
else
set childSet=parent.childNodes
finded=FALSE
for j=0 to childSet.length-1
set child=childSet.item(j)
childName=child.nodeName
if strcomp(childName,keywords(key_i+1))=0 then
set stack(top,0)=child
stack(top,1)=key_i+1
top=top+1
finded=TRUE
end if
next
if finded=FALSE then
for k=0 to childSet.length-1
set child=childSet.item(k)
set stack(top,0)=child
stack(top,1)=key_i
top=top+1
next
end if
end if
wend
%>
</p>
</form>
<p>
<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=5,0,0,0" width="144" height="39">
<param name="movie" value="button3.swf">
<param name="quality" value="high">
<param name="base" value=".">
<param name="bgcolor" value="#006666">
<embed src="button3.swf" width="144" height="39" base="." quality="high" pluginspage="http://www.macromedia.com/shockwave/download/index.cgi?P1_Prod_Version=ShockwaveFlash" type="application/x-shockwave-flash" bgcolor="#006666"></embed>
</object>
</p>
</div></td>
</tr>
<tr>
<td height="36" colspan="2" valign="top"><table width="100%" border="0" cellpadding="0" cellspacing="0">
<!--DWLayoutTable-->
<tr>
<td width="383" height="26" valign="top"><font color="#66FFFF" size="4"></font></td>
<td width="151" valign="top"><div align="center"><a href="main.htm"><font color="#33FFFF">返回</font></a></div></td>
</tr>
</table></td>
</tr>
</table>
</div></td>
<td width="2"></td>
</tr>
</TABLE>
<CENTER>
</DIV>
</CENTER></BODY></HTML>