[XML]學習筆記(九)DOM

DOM是一個使程序和腳本有能力動態的訪問和更新文檔的內容、結構以及樣式的平臺和語言中立的接口,主要被分爲三個不同的部分:核心DOM、XML DOM和HTML DOM。http://www.w3school.com.cn/xmldom/dom_intro.asp

一、JAXP接口(Java API for XMLParsing

a)        org.w3c.dom W3C推薦的用於XML標準規劃文檔對象模型的接口。

b)        org.xml.sax 用於對XML進行語法分析的事件驅動的XML簡單API(SAX)。

c)        javax.xml.parsers解析器工廠工具,程序員獲得並配置特殊的特殊語法分析器。

二、這三個包在jdk中都有

三、XML DOM的主要用途:

XML DOM(Document Object Model)即XML文檔對象模型,它定義了訪問和處理XML文檔的標準方法,或者說XML DOM是用於獲取、更改、添加或刪除XML元素的標準。

主要應用於:

1)        在需要修改XML文檔的內容、結構和順序時;

2)        需要多次遍歷XML文檔時;

3)        歸併多個XML文檔時;

4)        對XML內容做複雜操作

DOM的工作流程:

DOM解析器將整篇的XML文檔加載到內存中,並以的形式保存,含有豐富的API,所有對象在DOM中都被看作是Node/節點

四、XML DOM解析的基本步驟:

a)        應用程序生成DOM解析器

b)        解析器加載XML

c)        解析器嚮應用程序返回錯誤信息

d)        解析器生成DOM樹

e)        應用程序讀寫DOM樹

f)         應用程序將DOM樹轉化爲XML文檔輸出


五、DOM樹:

a)        抽象的:


b)        真實的:


六、XML DOM常用節點

DOM規定,XML文檔中的每個成分都是一個節點

a)        Document——整個文檔爲一個文檔節點documentElement,代表整個文檔,只有一個元素子節點root,但可以有多個其它類型的子節點;

而DocumentFragment表示一個XML片段,用於修改DOM樹、截取與合併XML片段。

b)        Element——每個XML標籤爲一個元素節點;

c)        Text——包含在XML元素中的文本是文本節點;注意文本總是存儲在文本節點中,元素節點不包含文本,元素節點的文本也是存儲在文本節點中的,如<name>CHZH<name>,CHZH不是name的值,而是name擁有一個值爲CHZH的文本節點。

d)        Attr——每個XML屬性是一個屬性節點,注意屬性節點和元素節點不存在父子關係;

e)        註釋屬於註釋節點。


七、解析XML DOM

f)         如下面的JavaScript片段將books.xml載入瞭解析器:

xmlDoc=newActiveXObject("Microsoft.XMLDOM"); #創建空的微軟XML文檔對象

<!--xmlDoc=document.implementation.createDocument("","",null)  --> #創建Firefox或其他瀏覽器中的空的XML文檔對象

xmlDoc.async="false";#關閉異步加載,確保在文檔加載完整前解析器不會繼續執行腳本

xmlDoc.load("books.xml");#加載books.xml

load()用於加載文件,而loadXML()用於加載字符串/文本。

一個跨瀏覽器解析XML文檔的實例:

<html>
<body>
<script type="text/javascript">
try //IE
  {
  xmlDoc=new ActiveXObject("Microsoft.XMLDOM");
  }
catch(e)
  {
  try //Firefox, Mozilla, Opera, etc.
    {
    xmlDoc=document.implementation.createDocument("","",null);
    }
  catch(e) {alert(e.message)}
  }
try 
  {
  xmlDoc.async=false;
  xmlDoc.load("books.xml");
  document.write("xmlDoc is loaded, ready for use");
  }
catch(e) {alert(e.message)}
</script>
</body>
</html>

 

g)        如下面的JavaScript片段把名爲txt的字符串載入解析器:

parser=new DOMParser(); #創建一個空的XML文檔對象
xmlDoc=parser.parseFromString(txt,"text/xml"); #告知解析器加載名爲txt的字符串

IE使用loadXML()解析XML字符串,方法同上面解析XML文檔的方法,需要創建xmlDoc文檔對象,並且需要關閉異步加載;而其他瀏覽器使用DOMParser()對象。

一個跨瀏覽器解析XML字符串的例子:

<html>
<body>
<script type="text/javascript">
text="<bookstore>"
text=text+"<book>";
text=text+"<title>Harry Potter</title>";
text=text+"<author>J K. Rowling</author>";
text=text+"<year>2005</year>";
text=text+"</book>";
text=text+"</bookstore>";
 
try //IE
  {
  xmlDoc=new ActiveXObject("Microsoft.XMLDOM");
  xmlDoc.async="false";
  xmlDoc.loadXML(text);
  }
catch(e)
  {
  try //Firefox, Mozilla, Opera, etc.
    {
    parser=new DOMParser();
    xmlDoc=parser.parseFromString(text,"text/xml");
    }
  catch(e) {alert(e.message)}
  }
document.write("xmlDoc is loaded, ready for use");
</script>
</body>
</html>

 

八、XML DOM加載函數

爲了避免編寫重複的代碼,將一些代碼存儲在函數中,並可以使用XML DOM加載。如上面的加載XML文檔代碼可定義爲loadXMLDoc(dname)函數,存儲在"loadxmldoc.js"文件中:

function loadXMLDoc(dname) 
{
try //Internet Explorer
  {
  xmlDoc=new ActiveXObject("Microsoft.XMLDOM");
  }
catch(e)
  {
  try //Firefox, Mozilla, Opera, etc.
    {
    xmlDoc=document.implementation.createDocument("","",null);
    }
  catch(e) {alert(e.message)}
  }
try 
  {
  xmlDoc.async=false;
  xmlDoc.load(dname);
  return(xmlDoc);
  }
catch(e) {alert(e.message)}
return(null);
}

在使用過程中,可以直接引用該函數:

<html>
<head>
<script type="text/javascript" src="loadxmldoc.js"> #先創建一個指向該函數存儲文件鏈接
</script>
</head>
 
<body>
<script type="text/javascript">
xmlDoc=loadXMLDoc("books.xml"); #加載books.xml文檔
document.write("xmlDoc is loaded, ready for use");
</script>
</body>
</html>

 

九、 XML DOM屬性和方法:設x爲一個節點對象


h) 常用的屬性:
i. x.nodeName:x的名稱;
ii. x.nodeValue:x的文本值;
iii. x.parentNode:x的父節點;
iv. x.childNodes:x的子節點;

v. x.attributes:x的屬性節點。


i) 常用的方法:
i. x.getElementsByTagName(name):獲取標籤名稱爲name的所有元素;
ii. x.appendChild(node):向x插入子節點node
iii. x.removeChild(node):從x刪除子節點node

如源books.xml爲:

<?xml version="1.0" encoding="ISO-8859-1"?>
 
<bookstore>
 
<book category="COOKING">
  <title lang="en">Everyday Italian</title>
  <author>Giada De Laurentiis</author>
  <year>2005</year>
  <price>30.00</price>
</book>
 
<book category="CHILDREN">
  <title lang="en">Harry Potter</title>
  <author>J K. Rowling</author>
  <year>2005</year>
  <price>29.99</price>
</book>
 
<book category="WEB">
  <title lang="en">XQuery Kick Start</title>
  <author>James McGovern</author>
  <author>Per Bothner</author>
  <author>Kurt Cagle</author>
  <author>James Linn</author>
  <author>Vaidyanathan Nagarajan</author>
  <year>2003</year>
  <price>49.99</price>
</book>
 
<book category="WEB">
  <title lang="en">Learning XML</title>
  <author>Erik T. Ray</author>
  <year>2003</year>
  <price>39.95</price>
</book>
 
</bookstore>

通過java程序testDOM.java來對books.xml進行訪問:

import java.io.File;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
public class testDOM {
         public static void main(String[] args) throws Exception {
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        DocumentBuilder builder = factory.newDocumentBuilder();
        File f = new File("books.xml");
        Document doc = builder.parse(f);
        Element root = doc.getDocumentElement();
        NodeList list = root.getElementsByTagName("book");
         
        for (int i = 0; i < list.getLength(); i++) {
            Element n = (Element) list.item(i);
            NamedNodeMap node = n.getAttributes();
            for (int x = 0; x < node.getLength(); x++) {
                Node nn = node.item(x);
                System.out.println(nn.getNodeName() + ": " + nn.getNodeValue());
            }
            System.out.println("title: " +n.getElementsByTagName("title").item(0).getFirstChild().getNodeValue());
            System.out.println("author: " + n.getElementsByTagName("author").item(0).getFirstChild().getNodeValue());
            System.out.println();
        }
    }
}

得到的結果爲:

category:COOKING

title: EverydayItalian

author: Giada DeLaurentiis

 

category:CHILDREN

title: HarryPotter

author: J K.Rowling

 

category: WEB

title: XQueryKick Start

author: JamesMcGovern

 

category: WEB

title: LearningXML

author: Erik T.Ray

十、XML DOM訪問節點的三種方式:

j)          通過x.getElementByTagName(name)指定節點標籤名的方式訪問,注意該訪問方式爲x下所有含有<name>標籤的元素,如需訪問整個文檔中所有的<name>元素,則使用xmlDoc.getElementByTagName(name);該方式獲得的結果爲一個節點列表(NodeList),可以通過下標訪問,如x[0]。

k)        通過遍歷節點樹的方式訪問,如在java中是通過getLength()獲取當前NodeList的節點數,然後使用NodeList.item(i)的方式訪問,其中i爲從0起始的下標;

x=xmlDoc.documentElement.childNodes;
for (i=0;i<x.length;i++)
{ 
if (x[i].nodeType==1)
  {//Process only element nodes (type 1) 
  document.write(x[i].nodeName);
  document.write("<br />");
  }
}

l)          通過節點關係進行訪問,如

         x=xmlDoc.getElementsByTagName("book")[0].childNodes;
         y=xmlDoc.getElementsByTagName("book")[0].firstChild;

 

十一、      XML DOM獲取節點信息:

a) nodeName:規定節點的名稱:
i. nodeName是隻讀的;
ii. 元素節點的nodeName即標籤名;
iii. 屬性節點的nodeName即屬性名;
iv. 文本節點的nodeName即#text;

v. 文檔節點的nodeName即#document。


b) nodeValue:規定節點的值:
i. nodeValue可修改,可以通過直接的賦值語句更改;
ii. 元素節點的nodeValue爲undefined;
iii. 屬性節點的nodeValue爲屬性值;
iv. 本文節點的nodeValue爲文本內容;


c) nodeType:規定節點的類型,只讀。

元素類型

節點類型

元素

1

屬性

2

文本

3

註釋

8

文檔

9

 

十二、      Node List節點列表

a) Node List對象會保持更新,每當添加或刪除元素後,列表信息都會被更新;
b) 獲得屬性列表Attribute List:如xmlDoc.getElementsByTagName('book')[0].attributes,與節點列表相同,會保持更新。

十三、      DOM中的空白與換行

XML 經常在節點之間含有換行或空白字符,Firefox以及其他一些瀏覽器,會把空白或換行作爲文本節點來處理,而 Internet Explorer則不會。

如果需要忽略元素節點之間的空文本節點,則需要進行節點類型檢查,只對於nodeType爲1的節點進行處理。

functionget_nextSibling(n)

{

y=n.nextSibling;

while (y.nodeType!=1)

  {

  y=y.nextSibling;

  }

return y;

}

 

十四、      XML DOM節點值操作:

a) 元素節點操作:
i. 獲取:nodeValue屬性用於獲取節點的文本節點(一般也將文本節點稱爲該節點的子節點)的值;
ii. 修改:可以通過爲nodeValue直接賦值進行更改值操作。
iii. 刪除:可以通過parentNode.removeChild(childNode)來刪除parentNode下的childNode節點,刪除一個節點後其所有的子節點都會被刪除。removeChild()同樣可以用來刪除文本節點,當然,對文本節點直接賦值爲""也可得到刪除的效果。
iv. 替換:x.replaceChild(origNode, newNode),其中x爲文檔的根節點xmlDoc.documentElement。
v. 創建:xmlDoc.createElement(nodeName),創建一個名爲nodeName的節點。
vi. 添加:parentNode.appendChild(childNode) 方法向已存在的節點添加子節點。parentNode.insertBefore(newChildNode,selectedNode) 方法用於在parentNode的子節點selectedNode之前插入節點newChildNode,如果子節點參數爲null,則插到最後一個子節點後面,與appendChild()功能相同。
vii. 克隆:newNode=oldNode.cloneNode(true|false),true和false表示新的節點是否克隆源節點的所有屬性和子節點。

如:

xmlDoc=loadXMLDoc("books.xml");
x=xmlDoc.getElementsByTagName("title")[0];
y=x.childNodes[0];#y爲第一個title的文本節點
txt=x.nodeValue; #txt爲文本元素
x.removeChild(y);

 

b) 屬性節點操作:
i. 獲取:getAttribute()方法返回屬性的值。
ii. 修改:setAttribute(attrName, newValue)方法用於設置屬性的值,如果attrName不存在,則創建一個attrName屬性,並將值賦爲newValue。當然,也可以在獲取屬性節點後直接通過nodeValue進行賦值操作修改其值。
iii. 刪除:removeAttribute(attrName)可以用於刪除指定的屬性。
iv. 創建:xmlDoc.createAttribute(attrName),創建一個名爲attrName的屬性,設爲newAttr,然後可以通過newAttr.nodeValue設置屬性值。通過對於某個元素節點x可以通過x.setAttributeNode(newAttr)的方式添加屬性。除此之外,利用setAttribute()可以直接創建沒有出現過的屬性。
v. 添加:通過x.setAttributeNode(newAttr)的方式添加屬性。

如:

xmlDoc=loadXMLDoc("books.xml");
x=xmlDoc.getElementsByTagName("title")[0].getAttributeNode("lang");
txt=x.nodeValue;


c) 文本節點操作:
vi. 創建:xmlDoc.createTextNode(textValue),創建一個值爲textValue的文本節點。
vii. 替換:x.replaceData(offset, length, string),x爲文本節點,其中offset表示從何處開始替換,以0開始;length表示被替換的字符個數;string表示新的要插入的字符串。當然,通過nodeValue也可以完成替換操作。
viii. 添加:x.insertData(offset, string),x爲文本節點,其中offset表示從何處添加,以0開始;string表示新的要插入的字符串。
d) CDATA Section節點操作:
ix. 創建:xmlDoc.createCDATASection(CDATAValue),創建一個值爲CDATAValue的CDATA Section節點。
e) 註釋節點操作:
x. 創建:xmlDoc.createComment(commentValue),創建一個值爲commentValue的註釋節點。


十五、      XML DOM解析器的生成(四步):

DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();#生成實例,工廠模式類似於new,但比new靈活,見http://blog.csdn.net/cristianojason/article/details/51510093
Factory.setValidating(false);#設定解析選項
DocumentBuilder builder = factory.newDocumentBuilder();#從factory中生成builder
Document doc = builder.parse(xmlFileURL);#解析文檔

                   XMLDOM遍歷解析樹:

 Element root = doc.getDocumentElement();#獲得root實例
NodeList children = root.getChildNodes();#獲得所有節點

 

十六、      構造新的DOM樹(五步):

Document newDoc = DocumentBuilder.newDocument();#定義新的Document
Element newRoot = newDoc.createElement(“rootName”);#建立新的根節點newRoot
#第三步自頂向下的構建分支
#第四步插入分支
newDoc.appendChild(newRoot)#第五步將newRoot插入到newDoc

 

十七、      XML DOM進行文檔歸併:

a)        解析兩個文檔;

b)        import被歸併文檔;

c)        將被歸併文檔的節點插入目標文檔的適當位置;

如:

Document doc1 = builder.parse(xmlFileURL1);
Document doc2 = builder.parse(xmlFileURL2);
Element root1 = doc1.getDocumentElement();
Element root2 = doc2.getDocumentElement();
NodeList children = root1.getChildNodes();
for(int i = 0; i < children.getLength(); i++) {
     Element newChild = (Element)children.item(i);
     Node newImportedChild = doc1.importNode(newChild, true);
     root1.appendChild(newImportedChild);
}

 

十八、      DOM應用程序:

a)  生成解析器(四步)

          i. 定義factory

          ii. 配置解析器

          iii.生成解析器

          iv. 解析文檔

b)  處理錯誤和異常

c)  遍歷DOM樹

d)  處理文檔

        i. 修改內容

        ii. 修改結構

        iii. 移動節點


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章