XML DOM介紹和例子
1.文檔對象模型(DOM)
DOM是HTML和XML文檔的編程基礎,它定義了處理執行文檔的途徑。編程者可以使用DOM增加文檔、定位文檔結構、填加修改刪除文檔元素。W3C 的重要目標是把利用DOM提供一個使用于多個平臺的編程接口。W3C DOM被設計成適合多個平臺,可使用任意編程語言實現的方法。
2.節點接口
XML parser用來裝載XML文檔到緩存中,文檔裝載時,可以使用DOM進行檢索和處理。DOM采用樹形結構表示XML文檔,文檔元素是樹的最高階層,該元素有一個或多個孩子節點用來表示樹的分枝。
節點接口程序通常用來讀和寫XML節點樹中的個別元素,文檔元素的孩子節點屬性可以用來構造個別元素節點。XML parser用來證明Web中的DOM支持遍歷節點樹的所有函數,并可通過它們訪問節點和及其屬性、插入刪除節點、轉換節點樹到XML中。
所有Microsoft XML parser函數得到W3C XML DOM的正式推薦,除了load和 loadXML函數(正式的DOM不包括標準函數loading XML文檔)。有13個節點類型被Microsoft? XML parser支持,下面列出常用節點:
節點類型例子
Document type <!DOCTYPE food SYSTEM "food.dtd">?
Processing instruction <?xml version="1.0"?>?
Element <drink type="beer">Carlsberg</drink>?
Attribute type="beer"?
Text Carlsberg?
?
?
3.使用XML parser
為了更加熟練的處理XML文檔,必須使用XML parser。Microsoft XML parser是IIS5.0所帶的一個COM組件,一旦安裝了IIS5.0,parser可以利用HTML文檔和ASP文件中的腳本。
Microsoft XMLDOM parser支持以下編程模式:
----支持JavaScript, VBScript, Perl, VB, Java, C++ 等等
----支持W3C XML 1.0 和XML DOM?
----支持DTD 和validation?
如果使用IE5.0中的JavaScript,可以使用下面的XML文檔對象:
var xmlDoc = new ActiveXObject("Microsoft.XMLDOM")
如果使用VBScript,可以使用下面的XML文檔對象:
set xmlDoc = CreateObject("Microsoft.XMLDOM")
如果使用ASP,可以使用下面的XML文檔對象:
set xmlDoc = Server.CreateObject("Microsoft.XMLDOM")
4.裝載一個XML文件到parser中
下面的代碼裝載存在的XML文檔進入XML parser:
<script language="JavaScript">
var xmlDoc = new ActiveXObject("Microsoft.XMLDOM")
xmlDoc.async="false"
xmlDoc.load("note.xml")
// ....... processing the document goes here
</script>
第一行腳本增加了一個Microsoft XML parser實例,第三行裝載名為”note.xml”的XML文檔進入parser中。第二行保證文檔裝載完成以后parser進行下一步工作。
5. parseError對象
打開XMl文檔時,XML Parser產生錯誤代碼,并存在parseError對象中,包括錯誤代碼、錯誤文本和錯誤行號,等信息。
6.文件錯誤
下面的例子將試圖裝載一個不存在的文件,然后產生相應的錯誤代碼:
var xmlDoc = new ActiveXObject("Microsoft.XMLDOM")
xmlDoc.async="false"
xmlDoc.load("ksdjf.xml")
document.write("<br>Error Code: ")
document.write(xmlDoc.parseError.errorCode)
document.write("<br>Error Reason: ")
document.write(xmlDoc.parseError.reason)
document.write("<br>Error Line: ")
document.write(xmlDoc.parseError.line)
7.XML錯誤
下面使用不正確的格式裝載XMl文檔,
var xmlDoc = new ActiveXObject("Microsoft.XMLDOM")
xmlDoc.async="false"
xmlDoc.load("note_error.xml")
document.write("<br>Error Code: ")
document.write(xmlDoc.parseError.errorCode)
document.write("<br>Error Reason: ")
document.write(xmlDoc.parseError.reason)
document.write("<br>Error Line: ")
document.write(xmlDoc.parseError.line)
8. parseError屬性
屬性描述:
errorCode 返回長整型錯誤代碼
reason 返回字符串型錯誤原因
line 返回長整型錯誤行號
linePos 返回長整型錯誤行號位置
srcText 返回字符串型產生錯誤原因
url 返回url裝載文檔指針
filePos 返回長整型錯誤文件位置
9.遍歷節點樹
一種通用的析取XML文檔的方法是遍歷節點樹和它的元素值。下面是使用VBScript寫的遍歷節點樹的程序代碼:
set xmlDoc=CreateObject("Microsoft.XMLDOM")
xmlDoc.async="false"
xmlDoc.load("note.xml")
for each x in xmlDoc.documentElement.childNodes
document.write(x.nodename)
document.write(": ")
document.write(x.text)
next?
10.為XML文件提供HTML格式
XML的一個優點是把HTML文檔和它的數據分離開。通過使用瀏覽器中的XML parser,HTML頁面可以被構造成靜態文檔,通過JavaScript提供動態數據。下面的例子使用JavaScript讀取XML文檔,寫XML數據成HTML元素:
var xmlDoc = new ActiveXObject("Microsoft.XMLDOM")
xmlDoc.async="false"
xmlDoc.load("note.xml")
nodes = xmlDoc.documentElement.childNodes
to.innerText = nodes.item(0).text
from .innerText = nodes.item(1).text
header.innerText = nodes.item(2).text
body.innerText = nodes.item(3).text
11.通過名稱訪問XML元素
下面的例子使用JavaScript讀取XML文檔,寫XML數據成HTML元素:
var xmlDoc = new ActiveXObject("Microsoft.XMLDOM")
xmlDoc.async="false"
xmlDoc.load("note.xml")
document.write(xmlDoc.getElementsByTagName("from").item(0).text)
12.裝載純XML文本進入parser?
下面的代碼裝載文本字符串進入XML parser :
<script language="JavaScript">
var text="<note>"
text=text+"<to>Tove</to><from>Jani</from>"
text=text+"<heading>Reminder</heading>"
text=text+"<body>Don't forget me this weekend!</body>"
text=text+"</note>"
var xmlDoc = new ActiveXObject("Microsoft.XMLDOM")
xmlDoc.async="false"
xmlDoc.loadXML(text)
// ....... processing the document goes here
</script>
13.裝載XML進入Parser?
<html>
<body>
<script language="javascript">
var xmlDoc = new ActiveXObject("Microsoft.XMLDOM")
xmlDoc.async="false"
xmlDoc.load("note.xml")
document.write("The first XML element in the file contains: ")
document.write(xmlDoc.documentElement.childNodes.item(0).text)
</script>
</body>
</html>
???? 遍歷XML節點樹:
<html>
<body>
<script language="VBScript">
txt="<h1>Traversing the node tree</h1>"
document.write(txt)
set xmlDoc=CreateObject("Microsoft.XMLDOM")
xmlDoc.async="false"
xmlDoc.load("note.xml")
for each x in xmlDoc.documentElement.childNodes
document.write("<b>" & x.nodename & "</b>")
document.write(": ")
document.write(x.text)
document.write("<br>")
next
</script>
</body>
</html>
裝載XML 進入HTML?
<html>
<head>
<script language="JavaScript"
for="window" event="onload">
var xmlDoc = new ActiveXObject("Microsoft.XMLDOM")
xmlDoc.async="false"
xmlDoc.load("note.xml")
nodes = xmlDoc.documentElement.childNodes
to.innerText = nodes.item(0).text
from.innerText = nodes.item(1).text
header.innerText = nodes.item(2).text
body.innerText = nodes.item(3).text
</script>
<title>HTML using XML data</title>
</head>
<body bgcolor="yellow">
<h1>Refsnes Data Internal Note</h1>
<b>To: </b><span id="to"></span>
<br>
<b>From: </b><span id="from"></span>
<hr>
<b><span id="header"></span></b>
<hr>
<span id="body"></span>
</body>
</html>
1、DOM樹?
所有類型的XML解析器都要求處理對象是“格式良好”的XML文檔,有些還能根據DTD或XML Schema進行有效性驗證,DOM (Document Object Model)解析器將XML文檔一次性解析,生成一個位于內存中的對象樹用以描述該文檔。??
DOM是一種與平臺和語言無關的接口,它允許程序和腳本動態訪問和修改文檔的內容、結構和類型。它定義了一系列的對象和方法對DOM樹的節點進行各種隨機操作:?
● Document對象:作為樹的最高節點,Document對象是對整個文檔進行操作的入口。?
● Element和Attr對象:這些節點對象都是文檔某一部分的映射,節點的定級層次恰好反映了文檔的結構。?
● Text對象:作為Element和Attr對象的子節點,Text對象表達了元素或屬性的文本內容。Text節點不再包含任何子節點。?
● 集合索引:DOM提供了幾種集合索引方式,可以對節點按指定方式進行遍歷。索引參數都是從0開始記數的。
DOM樹中的所有節點都是從Node對象繼承而來的。Node對象定義了一些最基本的屬性和方法,利用這些方法可以實現對樹的遍歷,同時,根據屬性還可以得知節點的名稱、取值并判斷其類型。?
利用DOM,開發人員可以動態地創建XML、遍歷文檔、增加/刪除/修改文檔內容。DOM提供的API與編程語言無關,所以對一些DOM標準中沒有明確定義的接口,不同解析器的實現方法也可能有所差別。為方便描述,本文的舉例均采用MSXML DOM方案并用VB Script編寫代碼。?
2、DOM樹的結構?
Document對象建立之后,就可以與XML文檔或數據島聯系在一起。數據島的加載方法是將數據島ID賦給Document對象:?
<XML ID=“dsoDetails” src=“Books.xml”></XML>?
Set doc = dsoDetails.XMLDocument?
加載文檔大體上分為三步:?
1.使用CreateObject方法創建分析器實例;?
2.設置async屬性為False,禁止異步加載,這樣當文檔加載完畢,控制權才會返回給調用進程,如果想獲取文檔加載狀態,可以讀取readyState屬性值;?
3.使用load方法加載指定文檔。?
Set doc = CreateObject(“Microsoft.XMLDOM”)?
doc.async = False?
doc.load “Books.xml”?
XML DOM還提供了一種loadXML的方法可以把XML字符串加載到DOM樹中,使用時只要把XML字符串直接作為該方法的參數即可。?
3、DOM樹的訪問?
在文檔加載完畢之后就可以使用documentElement屬性訪問根元素:?
Set rootNode = doc.documentElement?
一旦建立了對DOM樹中某個節點(例如根節點)的引用,就可以根據節點間的等級關系調用適當的方法進行遍歷。?
下面以books.xml為例說明各種方法的使用:?
<xml id=“dsoBooks”>?
<?xml version=“1.0”?>
<booklist>
<book>?
<title>The Gourmet Microwave</title>??
<price>9.95</price>?
<author>Charlotte M. Cooper</author>?
<author>Shelley B. Burke</author>?
<author>Regina P. Murphy</author>?
</book>
<book>?
<title>Sushi, Anyone?</title>??
<price>14.99</price>
</book>
<book>?
<title>Straight Talk About Computers</title>
?<price>19.99</price>?
<author>Lars Peterson</author>?
</book>
</booklist></xml>?
建立對第二個<book>元素的引用:?
Set theNode =dsoBooks.XMLDocument.documentElement.childNodes(1)?
● 根節點:theNode.ownerDocument返回Document節點,指向XML文檔本身;?
● 兄弟節點:theNode.previousSibling返回第1個<book>元素,theNode.nextSibling返回第3個<book>元素;?
● 父節點:theNode.parentNode返回<booklist>元素;?
● 子節點:theNode.firstChild返回<title>元素,theNode.lastChild返回< price>元素,theNode.childNodes返回子節點集合,包括Sushi下面的所有元素。節點記數從0開始,即 theNode.childNodes(0)的結果與theNode.firstChild的結果是一樣的。?
獲得節點的引用后,就可以讀取節點的相關信息:?
● 節點類型:theNode.nodeType,本例為1,Document對象類型為9,元素類型為1,屬性類型為2;?
● 節點名稱:theNode.nodeName,本例為book;?
● 節點值:theNode.nodeValue,本例為null,對于Attr節點,返回的是屬性值,而對于Element節點,返回的是null。?
在MSXML中,對Node對象還提供了一些額外的方法和屬性:?
● nodeTypeString:用字符串的方式顯示節點類型,如theNode.nodeTypeString的結果是“element”;?
● text: 顯示當前節點及其所有子節點的文本內容;?
● xml:獲取XML文檔數據,通常是從根元素開始的所有內容。
4、XML格式的動態轉換?
通過學習XSL,我們已經能夠使用樣式單對XML文檔進行轉換。但這種過程是靜態的,即在編寫代碼時,已經指定了作用在XML上的XSL文件,在程序運行過程中不能再做改變。而利用DOM,我們能夠實現XML格式的動態轉換,即在程序運行時,將XSL載入并對XML文檔進行轉換。?
把XSL載入DOM對象的步驟基本上與XML文檔的載入過程是一樣的(XSL本身就是XML文檔):?
Set stylesheet = CreateObject(“Microsoft.XMLDOM”)?
stylesheet.async = False?
stylesheet.load “TransformDetails.xsl”?
DOM提供了兩個函數進行這種轉換,作用對象可以是樹中任何節點。這樣就可以實現對DOM樹的任意的部分進行格式轉換。?
● transformNodeToObject方法:該方法需要兩個參數,第一個參數指向XSL文件,第二個參數存放轉換后的XML數據的節點。例如:?
Set targetNode = CreateObject(“Microsoft.XMLDOM”)?
srcNode.transformNodeToObject stylesheet, targetNode?
● transformNode方法:該方法只需要一個參數指明XSL文件。如下例是將源節點轉換為一個字符串變量str:?
str = srcNode.transformNode(stylesheet)?
1、DOM解析時的錯誤?
DOM在解析XML文檔的時候可能會產生各式各樣的錯誤,可以根據ParseError對象中的屬性得知出錯的可能原因及相關信息。?
常用的屬性及其含義如下表所示:?
屬性 說明?
errorCode 錯誤代碼?
filepos 錯誤在文檔中的絕對字符位置?
line 錯誤所在行的行號?
linepos 錯誤所在行的字符位置?
reason 錯誤產生原因?
srcText 錯誤所在行的源代碼?
url 最近一份含有解析錯誤的XML文檔的URL地址?
?
?
2、訪問DOM樹中的元素與屬性?
DOM還提供了許多查找節點的方法。其中基于搜索機制的方法有:?
● 根據標簽名稱搜索元素;?
● 使用XSL模式搜索節點;?
● 利用集合索引搜索節點。?
以books.xml為例,Document對象中的getElementsByTagName方法就是根據參數中的標簽名稱在全文范圍內查找元素的,返回值是一個NodeList對象:?
Set doc = dsoDetails.XMLDocument??
Set authors = doc.getElementsByTagName(“author”)?
上述查詢結果中包含了文檔中出現的全部4位作者。如果調用的是Element對象中的getElementsByTagName方法,除了搜索范圍縮小為該元素的所有后繼節點之外,其他的情況都是一樣的。?
所有類型的節點都帶有selectNodes方法,該方法的唯一參數是XSL的模式規則,返回值是匹配該規則的結果集合。調用這個方法可以利用XSL的模式匹配策略查找節點。例如:?
Set rootNode = doc.documentElement??
Set cheapbooks = rootNode.selectNodes(“//book[price < 10]”)?
這個例子返回所有售價低于10元的<book>元素。另外,節點中的selectSingleNodes方法的用法與selectNodes是一樣的,只是返回結果為查找到的滿足條件的第一個節點而已。
對于元素節點,獲取元素標簽名稱的方法有兩種:anyElement.nodeName和anyElement.tagName。前者是Node對象的屬性,后者是Element對象的屬性。?
如果想獲取元素中的文本內容,如: <price>9.95?
</price>時,訪問Element對象中的nodeValue屬性是錯誤的,這時返回結果是null,而不是預期的9.95。含有文本內容的元素都包含一個Text類型的子節點,所以只有通過Text對象中的nodeValue屬性才能真正訪問到文本內容。??
添加元素的步驟如下:?
● 創建一個Text節點并賦值;?
● 創建Element節點;?
● 把Text節點掛在Element節點下,作為它的子節點;?
● 把Element節點插入到XML文檔的合適位置上。?
對于元素節點的刪除和替換操作,首先都要對操作對象進行定位,然后相應地執行對象節點所屬父節點的removeChild方法和replaceChild方法即可。?
Attr節點的各種操作在原理上與Element節點相同。Attr對象同樣繼承了Node對象中的各種方法和屬性,并且MSXML中還提供了name屬性和value屬性,能夠更直接地訪問到屬性信息。另外,還可以通過屬性所屬元素的相關方法訪問屬性,如通過getAttribute和 setAttribute方法讀取屬性值或修改屬性值,或者用getAttributeNode方法直接返回Attr對象。?
創建新屬性最直接的辦法就是使用Element對象中的setAttribute方法。也可以先用Document對象中的 createAttribute方法設置屬性值,然后使用Element對象中的setAttributeNode方法把新節點添加到DOM樹中。同樣地,刪除屬性最直接的方法是調用Element中的removeAttribute方法。另外一種方案是先用getAttributeNode方法對操作對象進行定位,然后執行removeAttributeNode操作。?
從以上的介紹中可以看出,由于節點間的繼承關系,以及各種類型節點本身提供的豐富的接口,用戶可以很容易地找到一套適合自己需要的對象操作方案。?
??
3、DOM的顯示功能?
DOM技術還可以用來顯示XML數據。XSL樣式單面向的是XML文檔的轉換,用于顯示格式的轉換是其應用的一個方面,所以在顯示功能上還存在著一些不足:?
● 不易完成對XML數據的復雜處理,如將英文字母全部轉換為大寫,截取指定長度的字符串,忽略一些特定的標點等;?
● 不易對XML數據中的數值進行計算;?
● 一個XSL通常是靜態地作用到一個XML文檔上,無法將多個XML文檔中的數據用一個XSL合并轉換為一個輸出結果。?
使用DOM就能夠很好地解決上述問題
?