| <Phone>987-654-3210</Phone> |
| <Phone Type="WorkFax">987-654-3210<Phone> |
| <Phone Type="WorkFax" Number="987-654-3210" /> |
| <Addresses> ?。糆ntry Type="Personal"> ?。糉irstName>Andy</FirstName> ?。糒astName>Fickle</LastName> ?。糞treet>1234 Programmer Place</Street> ?。糃ity>Bugsville</City> ?。糞tate>CO</State> ?。糧ip>82379</Zip> ?。糚hone Type="Home">354-493-9489</Phone> ?。?Entry> ?。糆ntry Type="Work"> ?。糉irstName>Betty</FirstName> ?。糒astName>Masterson</LastName> ?。糚hone Type="Work">937-878-4958</Phone> ?。糚hone Type="WorkFax">937-878-4900</Phone> ?。?Entry> ... </Addresses> |
注意相似的節點(diǎn)不需要包含相同的信息,例如第一個(gè)Entry節點(diǎn)包含了地址信息和家庭電話(huà)號碼,第二個(gè)Entry節點(diǎn)包含了Work和WorkFax電話(huà)號碼,而沒(méi)有包含第一個(gè)Entry節點(diǎn)包含的信息。
XML工具
如前面的例子顯示,XML語(yǔ)法是如此的簡(jiǎn)單以至于你可以在很短的時(shí)間作一個(gè)XML解析器,幸運的是你不必這樣做,因為XML工具可以運行在各種平臺上,包括可以安裝了Visual Basic的Windows。
正是這些L工具而不是XML本身使XML變得更強大和復雜。不同的解析器使你可以某一時(shí)刻加載整個(gè)XML文檔或只加載某個(gè)節點(diǎn),與此相反,XML Writer 可以同時(shí)創(chuàng )建一個(gè)XML文檔和節點(diǎn)。
DOM解析器使我們能夠很方便的加載、復制、排序、修改和存儲XML文件,遍歷節點(diǎn)獲得名稱(chēng)或屬性,并給結果排序。雖然他們的功能沒(méi)有真正的關(guān)系數據庫強大,但DOM的這些特點(diǎn)依然非常有用。
XSD可以定義XML文檔的格式,XSL擴展樣式單定義了怎樣將XML文檔轉換成其他可以在WEB瀏覽器中瀏覽的文件格式,比如HTML文件。
這些工具實(shí)際上比XML本身更復雜,所以所有講解XML的書(shū)籍都花了很大的篇幅解釋這些XML工具。但這超出了本文的范圍,有興趣的讀者可以參考有關(guān)資料。
Visual Basic.Net提供了使用XML、XSL以及其他XML工具的完整工具。但不用等待VB.NET,微軟XML核心服務(wù)(MSXML)版本4.0提供了從Visual Basic6.0加載和存儲XML文檔的工具。
在msdn.microsoft.com/xml/default.asp中下載最新版本的MSXML,并安裝在計算機上。在Visual Basic 6.0中使用Microsoft XML V4.0象引用其他對象一樣,首先在工程菜單中選擇引用菜單項,選擇Microsoft V4.0,單擊OK,一切完成后就現在就可以在VB應用程序中添加X(jué)ML對象了。
DOMDocument 類(lèi)
文檔對象模型(DOM)使用了一系列相應的對象描述了XML文檔的等級狀態(tài),DOMDocument類(lèi)是一個(gè)描繪XML文檔的DOM結構的MSXML類(lèi)。
DOMDocument類(lèi)僅僅提供了很少的幾個(gè)有用的屬性和方法。Load方法載入一個(gè)xml文件,loadxml方法將字符串作為xml數據添加到對象中。例如,下面的代碼就將一個(gè)小的xml文件添加到名為xml_document的文檔中。
| Dim xml_document As New DOMDocument xml_document.loadXML _ "<Person>" & vbCrLf & _ " <FirstName>Rod</FirstName>" & vbCrLf & _ " <LastName>Stephens</LastName>" & vbCrLf & _ "</Person>" |
DOMDocument的xml屬性返回文檔的xml描述,可以顯示這些返回值看看這些文檔究竟是什么樣子,也可以將它存儲為一個(gè)文件,但這完全不必要,因為DOMDocument對象的save方法已經(jīng)自動(dòng)將他們存儲了。
DOMDocument對象的documentElement屬性表示文檔數據的根結點(diǎn),通常情況下操作XML文檔都從這里開(kāi)始。
DOMDocument提供了幾種創(chuàng )建新節點(diǎn)的方法。CreateElement方法為文檔創(chuàng )建一個(gè)新的元素節點(diǎn),其他創(chuàng )建節點(diǎn)的方法有createAttribute, createProcessingInstruction, 和 createTextNode,在這里就不一一介紹了。
IXMLDOMNode類(lèi)
IXMLDOMNode類(lèi)描述了一個(gè)節點(diǎn),該類(lèi)提供了一系列用于搜索和操縱XML文檔的屬性和方法。
selectSingleNode 方法用于搜索指定節點(diǎn)的后代,用于搜索指定節點(diǎn)路徑的語(yǔ)言稱(chēng)為XPATH,XPATH非常棘手,本文就不詳細說(shuō)明其規范了。下面我們將介紹兩個(gè)對搜索子節點(diǎn)有特別有用并且簡(jiǎn)單的方法。
在給selectsingleNode方法中輸入子節點(diǎn)的名字,該方法將在節點(diǎn)的子節點(diǎn)進(jìn)行精確匹配搜索。如果在輸入的字符串前面加上".//",那么將搜索節點(diǎn)的全部后代。
| ‘ Search for a child node named "LastName." Set last_name_node = address_node.selectSingleNode("LastName") ‘ Search for any descendant named "LastName." Set last_name_node = address_node.selectSingleNode(".//LastName") |
下面列出了IXMLDOMNode對象的部分非常有用的屬性:
attributes.節點(diǎn)屬性集合
nodeName.節點(diǎn)的標記名
nodeTypeString.節點(diǎn)的類(lèi)型
ownerDocument.返回DOMDocument對象包含的節點(diǎn)
text.表示節點(diǎn)包含的文本內容。如果該節點(diǎn)包含其他節點(diǎn),那么text代表了所有節點(diǎn)的文本內容的組合。
xml.給出了節點(diǎn)的xml內容,例如:"<FirstName>Rod</FirstName>".
ChildNodes集合包含了節點(diǎn)的子節點(diǎn)。要給節點(diǎn)增加一個(gè)子節點(diǎn),首先必須給使用DOMDocument對象的節點(diǎn)創(chuàng )建方法,然后將這個(gè)新建的節點(diǎn)加入到父節點(diǎn)的childNodes集合中。下面的代碼展示了創(chuàng )建一個(gè)新的子節點(diǎn)的子程序,并使用父節點(diǎn)的appendChild方法將其加入到父節點(diǎn)中:
| ‘ Add a new node to the indicated parent node. Private Sub CreateNode(ByVal indent As Integer, _ ByVal parent As IXMLDOMNode, ByVal node_name As String, _ ByVal node_value As String) Dim new_node As IXMLDOMNode ‘ Create the new node. Set new_node = parent.ownerDocument.createElement(node_name) ‘ Set the node‘s text value. new_node.Text = node_value ‘ Add the node to the parent. parent.appendChild new_node End Sub |
SaveValues 程序
現在我們可以使用XML創(chuàng )建一個(gè)簡(jiǎn)單的程序(如圖1),其值存儲到XML文件中,在程序開(kāi)始運行時(shí),程序從VALUE.XML文件中加載數據,在程序運行結束時(shí),將程序中的現行值存入VALUE.XML文件中。
下面的代碼是顯示了VALUE.XML文件的結構:
| <Values> ?。糉irstName>Rod</FirstName> ?。糒astName>Stephens</LastName> ?。糞treet>1234 Programmer Place</Street> ?。糃ity>Bugsville</City> ?。糞tate>CO</State> ?。糧ip>80276</Zip> </Values> |
List1顯示了怎樣編寫(xiě)SaveValues,當載入表單時(shí),form_load事件觸發(fā)LoadValues子程序。
LoadValues創(chuàng )建了一個(gè)名為xml_document的DOMDocument對象,然后載入xml文件,使用selectSingleNode方法查找名為values的節點(diǎn),然后使用GetNodeValue方法獲得從value節點(diǎn)后代中得到的值。
GetNodeValue使用value節點(diǎn)的selectSingleNode方法尋找目標節點(diǎn),如果節點(diǎn)不存在函數將返回一個(gè)缺省值,如果找到這個(gè)節點(diǎn)GetNodeValue將返回該節點(diǎn)的text值。對于value.xml文件中的數據節點(diǎn),text僅僅是包含在節點(diǎn)中的文本內容。
當窗體卸載時(shí)觸發(fā)form_unload事件,unload事件調用SaveValues子程序。程序創(chuàng )建一個(gè)新的DOMDocument對象,該對象創(chuàng )建一個(gè)新的名為value的節點(diǎn),然后用文檔的appendChild方法將節點(diǎn)添加到文檔中。
在創(chuàng )建所有新的節點(diǎn)后,SaveValues調用DOMDocument‘s save方法存儲新的xml文件。
注意這個(gè)新的文件已經(jīng)覆蓋了舊文件,使用DOMDocument對象無(wú)法部分改變XML文件,可以加載XML文件,然后修改其中一部分,然后保存文件,但原文件將被完全覆蓋。這是一個(gè)小的缺陷,但在這時(shí)可以使用其它程序進(jìn)行修改。
List1的最后一部分是CreateNode子程序,CreateNode 為父節點(diǎn)創(chuàng )建一個(gè)新節點(diǎn)并同時(shí)給這個(gè)節點(diǎn)賦值。在這個(gè)子程序中首先引用一個(gè)DOMDocument對象,然后使用該對象的createElement方法創(chuàng )建一個(gè)新的節點(diǎn)。
createNode方法設置節點(diǎn)的text屬性,然后將節點(diǎn)作為子節點(diǎn)添加到父節點(diǎn)中。
List1:
| Option Explicit Private m_AppPath As String Private Sub Form_Load() ‘ Get the application‘s startup path. m_AppPath = App.Path If Right$(m_AppPath, 1) <> "" Then m_AppPath = m_AppPath & "" ‘ Load the values. LoadValues End Sub Private Sub Form_Unload(Cancel As Integer) ‘ Save the current values. SaveValues End Sub ‘ Load saved values from XML. Private Sub LoadValues() Dim xml_document As DOMDocument Dim values_node As IXMLDOMNode ‘ Load the document. Set xml_document = New DOMDocument xml_document.Load m_AppPath & "Values.xml" ‘ If the file doesn‘t exist, then ‘ xml_document.documentElement is Nothing. If xml_document.documentElement Is Nothing Then ‘ The file doesn‘t exist. Do nothing. Exit Sub End If ‘ Find the Values section. Set values_node = xml_document.selectSingleNode("Values") ‘ Read the saved values. txtFirstName.Text = GetNodeValue(values_node, "FirstName", "???") txtLastName.Text = GetNodeValue(values_node, "LastName", "???") txtStreet.Text = GetNodeValue(values_node, "Street", "???") txtCity.Text = GetNodeValue(values_node, "City", "???") txtState.Text = GetNodeValue(values_node, "State", "???") txtZip.Text = GetNodeValue(values_node, "Zip", "???") End Sub ‘ Return the node‘s value. Private Function GetNodeValue(ByVal start_at_node As IXMLDOMNode, _ ByVal node_name As String, _ Optional ByVal default_value As String = "") As String Dim value_node As IXMLDOMNode Set value_node = start_at_node.selectSingleNode(".//" & node_name) If value_node Is Nothing Then GetNodeValue = default_value Else GetNodeValue = value_node.Text End If End Function ‘ Save the current values. Private Sub SaveValues() Dim xml_document As DOMDocument Dim values_node As IXMLDOMNode ‘ Create the XML document. Set xml_document = New DOMDocument ‘ Create the Values section node. Set values_node = xml_document.createElement("Values") ‘ Add the Values section node to the document. xml_document.appendChild values_node ‘ Create nodes for the values inside the ‘ Values section node. CreateNode values_node, "FirstName", txtFirstName.Text CreateNode values_node, "LastName", txtLastName.Text CreateNode values_node, "Street", txtStreet.Text CreateNode values_node, "City", txtCity.Text CreateNode values_node, "State", txtState.Text CreateNode values_node, "Zip", txtZip.Text ‘ Save the XML document. xml_document.save m_AppPath & "Values.xml" End Sub ‘ Add a new node to the indicated parent node. Private Sub CreateNode(ByVal parent As IXMLDOMNode, _ ByVal node_name As String, ByVal node_value As String) Dim new_node As IXMLDOMNode ‘ Create the new node. Set new_node = parent.ownerDocument.createElement(node_name) ‘ Set the node‘s text value. new_node.Text = node_value ‘ Add the node to the parent. parent.appendChild new_node End Sub |
SaveValuesIndented 程序
雖然每個(gè)人都化了很大的精力去處理xml文檔,使他們看上更容易些,但xml工具一般都忽略了那些使xml文檔結構明顯的空白和縮進(jìn),xml解析器也同樣忽略縮進(jìn)和空白。
不幸的是我們例子也同樣忽略了這些縮進(jìn)和空白,SaveValues創(chuàng )建了一個(gè)象下面那樣的xml文件,所有的代碼都在同一行中。
| <Values><FirstName>Rod</FirstName><LastName>Stephens</LastNa me><Street>1234 Programmer Place</Street><City>Bugsville</Ci ty><State>CO</State><Zip>80276</Zip></Values> |
| ‘ Save the current values. Private Sub SaveValues() Dim xml_document As DOMDocument Dim values_node As IXMLDOMNode ‘ Create the XML document. Set xml_document = New DOMDocument ‘ Create the Values section node. Set values_node = xml_document.createElement("Values") ‘ Add a new line. values_node.appendChild xml_document.createTextNode(vbCrLf) ‘ Add the Values section node to the document. xml_document.appendChild values_node ‘ Create nodes for the values inside the ‘ Values section node. CreateNode 4, values_node, "FirstName", txtFirstName.Text CreateNode 4, values_node, "LastName", txtLastName.Text CreateNode 4, values_node, "Street", txtStreet.Text CreateNode 4, values_node, "City", txtCity.Text CreateNode 4, values_node, "State", txtState.Text CreateNode 4, values_node, "Zip", txtZip.Text ‘ Save the XML document. xml_document.save m_AppPath & "Values.xml" End Sub ‘ Add a new node to the indicated parent node. Private Sub CreateNode(ByVal indent As Integer, _ ByVal parent As IXMLDOMNode, ByVal node_name As String, _ ByVal node_value As String) Dim new_node As IXMLDOMNode ‘ Indent. parent.appendChild parent.ownerDocument.createTextNode(Space$(indent)) ‘ Create the new node. Set new_node = parent.ownerDocument.createElement(node_name) ‘ Set the node‘s text value. new_node.Text = node_value ‘ Add the node to the parent. parent.appendChild new_node ‘ Add a new line. parent.appendChild parent.ownerDocument.createTextNode(vbCrLf) End Sub |
聯(lián)系客服