天天看點

利用Visual Basic操作XML資料

什麼是XML

  擴充标記語言XML是一種簡單的資料存儲語言,使用一系列簡單的标記描述資料,而這些标記可以用友善的方式建立,雖然XML占用的空間比二進制資料要占用更多的空間,但XML極其簡單易于掌握和使用。

  XML與Access,Oracle和SQL Server等資料庫不同,資料庫提供了更強有力的資料存儲和分析能力,例如:資料索引、排序、查找、相關一緻性等,XML僅僅是展示資料。事實上XML 與其他資料表現形式最大的不同是:他極其簡單。這是一個看上去有點瑣細的優點,但正是這點使XML與衆不同。

  XML的簡單使其易于在任何應用程式中讀寫資料,這使XML很快成為資料交換的唯一公共語言,雖然不同的應用軟體也支援其它的資料交換格式,但不久之後他們都将支援XML,那就意味着程式可以更容易的與Windows、Mac OS, Linux以及其他平台下産生的資訊結合,然後可以很容易加載XML資料到程式中并分析他,并以XML格式輸出結果。

  XML的優點

  我們談到XML長于在不同的應用程式之間交換資料,XML檔案也便于建構小的資料庫,不久以前,軟體都使用INI檔案存儲配置資訊、使用者參數以及其他資訊,後來微軟引入了系統系統資料庫,接作微軟告訴我們不應該再使用INI檔案了,從那時起Visual Basic對INI檔案的支援被削弱了。但不幸的是系統資料庫有幾個緻命的缺點:不是簡單的文本檔案,難于讀寫、可能會變得龐大和緩慢、如果系統資料庫不知何故出現問題,将有可能造成系統當機。

  将配置資訊放在XML檔案中可以避免這些問題,甚至可以将XML檔案設定為一個共享檔案,這樣在不同的計算機上的使用者就可以共享資料,這是系統資料庫所不能比拟的。

  在被稱為下一代ASP的ASP.NET中可以在WEB頁中直接使用XML,你可以使用資料綁定控件直接綁定資料并自動顯示。

  當然也可以不選擇XML,使用文本檔案、系統資料庫、資料庫都可以完成XML所能完成的任務,XML隻是你在資料存儲和恢複的另一種工具而已。

  XML文法簡介

  XML的文法非常的簡單,XML文檔由節點組成,使用打開和關閉節點描述标記,在格式上與HTML标記非常相似,它們之間最大的不同是:XML中可以自由定義标記名。比如下面的标記就描述了一個電話号碼:

<Phone>987-654-3210<Phone>

  而且不用聲明标記名就可以使用。

  開始和結束标記必須相同,XML是識别大小寫的,是以标記的大小寫也必須相同。比如上面的例子中以<Phone>标記開始就必須以<Phone>标記結束,而不能是<phone>或<PHONE>

  節點标記中可以包含屬性,比如下面的代碼中Phone節點包含屬性Type,其值為WorkFax

<Phone Type=WorkFax>987-654-3210<Phone>

  如果不願意在節點中包含一個值,那麼可以不需要結束标記,可以用在開始标記的後面加一個斜線來結束節點,在下面的例子中,Phone标記的Number屬性就存儲了一個電話号碼,是以就不需要一個結束标記:

<Phone Type=WorkFax Number=987-654-3210 >

  XML文檔的結構是一個樹形等級結構。文檔必須有一個唯一的根結點,根節點包含所有其它節點。下面我們舉一個較為完整的例子:

<Addresses>

 <Entry Type=Personal>

  <FirstName>Andy<FirstName>

  <LastName>Fickle<LastName>

  <Street>1234 Programmer Place<Street>

  <City>Bugsville<City>

  <State>CO<State>

  <Zip>82379<Zip>

  <Phone Type=Home>354-493-9489<Phone>

 <Entry>

 <Entry Type=Work>

  <FirstName>Betty<FirstName>

  <LastName>Masterson<LastName>

  <Phone Type=Work>937-878-4958<Phone>

  <Phone Type=WorkFax>937-878-4900<Phone>

 ...

  注意相似的節點不需要包含相同的資訊,例如第一個Entry節點包含了位址資訊和家庭電話号碼,第二個Entry節點包含了Work和WorkFax電話号碼,而沒有包含第一個Entry節點包含的資訊。

XML工具

  如前面的例子顯示,XML文法是如此的簡單以至于你可以在很短的時間作一個XML解析器,幸運的是你不必這樣做,因為XML工具可以運作在各種平台上,包括可以安裝了Visual Basic的Windows。

  正是這些L工具而不是XML本身使XML變得更強大和複雜。不同的解析器使你可以某一時刻加載整個XML文檔或隻加載某個節點,與此相反,XML Writer 可以同時建立一個XML文檔和節點。

  DOM解析器使我們能夠很友善的加載、複制、排序、修改和存儲XML檔案,周遊節點獲得名稱或屬性,并給結果排序。雖然他們的功能沒有真正的關系資料庫強大,但DOM的這些特點依然非常有用。

  XSD可以定義XML文檔的格式,XSL擴充樣式單定義了怎樣将XML文檔轉換成其他可以在WEB浏覽器中浏覽的檔案格式,比如HTML檔案。

  這些工具實際上比XML本身更複雜,是以所有講解XML的書籍都花了很大的篇幅解釋這些XML工具。但這超出了本文的範圍,有興趣的讀者可以參考有關資料。

  Visual Basic.Net提供了使用XML、XSL以及其他XML工具的完整工具。但不用等待VB.NET,微軟XML核心服務(MSXML)版本4.0提供了從Visual Basic6.0加載和存儲XML文檔的工具。

  在msdn.microsoft.comxmldefault.asp中下載下傳最新版本的MSXML,并安裝在計算機上。在Visual Basic 6.0中使用Microsoft XML V4.0象引用其他對象一樣,首先在工程菜單中選擇引用菜單項,選擇Microsoft V4.0,單擊OK,一切完成後就現在就可以在VB應用程式中添加XML對象了。

  DOMDocument 類

  文檔對象模型(DOM)使用了一系列相應的對象描述了XML文檔的等級狀态,DOMDocument類是一個描繪XML文檔的DOM結構的MSXML類。

  DOMDocument類僅僅提供了很少的幾個有用的屬性和方法。Load方法載入一個xml檔案,loadxml方法将字元串作為xml資料添加到對象中。例如,下面的代碼就将一個小的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描述,可以顯示這些傳回值看看這些文檔究竟是什麼樣子,也可以将它存儲為一個檔案,但這完全不必要,因為DOMDocument對象的save方法已經自動将他們存儲了。

  DOMDocument對象的documentElement屬性表示文檔資料的根結點,通常情況下操作XML文檔都從這裡開始。

  DOMDocument提供了幾種建立新節點的方法。CreateElement方法為文檔建立一個新的元素節點,其他建立節點的方法有 createAttribute, createProcessingInstruction, 和 createTextNode,在這裡就不一一介紹了。

  IXMLDOMNode類

  IXMLDOMNode類描述了一個節點,該類提供了一系列用于搜尋和操縱XML文檔的屬性和方法。

selectSingleNode 方法用于搜尋指定節點的後代,用于搜尋指定節點路徑的語言稱為XPATH,XPATH非常棘手,本文就不詳細說明其規範了。下面我們将介紹兩個對搜尋子節點有特别有用并且簡單的方法。

  在給selectsingleNode方法中輸入子節點的名字,該方法将在節點的子節點進行精确比對搜尋。如果在輸入的字元串前面加上.,那麼将搜尋節點的全部後代。

' 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.節點屬性集合

   nodeName.節點的标記名

   nodeTypeString.節點的類型

   ownerDocument.傳回DOMDocument對象包含的節點

   text.表示節點包含的文本内容。如果該節點包含其他節點,那麼text代表了所有節點的文本内容的組合。

   xml.給出了節點的xml内容,例如:<FirstName>Rod<FirstName>.

  ChildNodes集合包含了節點的子節點。要給節點增加一個子節點,首先必須給使用DOMDocument對象的節點建立方法,然後将這個建立的節點加入到父節點的childNodes集合中。下面的代碼展示了建立一個新的子節點的子程式,并使用父節點的appendChild方法将其加入到父節點中:

' 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建立一個簡單的程式(如圖1),其值存儲到XML檔案中,在程式開始運作時,程式從VALUE.XML檔案中加載資料,在程式運作結束時,将程式中的現行值存入VALUE.XML檔案中。

  下面的代碼是顯示了VALUE.XML檔案的結構

<Values>

 <FirstName>Rod<FirstName>

 <LastName>Stephens<LastName>

 <Street>1234 Programmer Place<Street>

 <City>Bugsville<City>

 <State>CO<State>

 <Zip>80276<Zip>

  List1顯示了怎樣編寫SaveValues,當載入表單時,form_load事件觸發LoadValues子程式。

  LoadValues建立了一個名為xml_document的DOMDocument對象,然後載入xml檔案,使用selectSingleNode方法查找名為values的節點,然後使用GetNodeValue方法獲得從value節點後代中得到的值。

  GetNodeValue使用value節點的selectSingleNode方法尋找目标節點,如果節點不存在函數将傳回一個預設值,如果找到這個節點GetNodeValue将傳回該節點的text值。對于value.xml檔案中的資料節點,text僅僅是包含在節點中的文本内容。

  當窗體解除安裝時觸發form_unload事件,unload事件調用SaveValues子程式。程式建立一個新的DOMDocument對象,該對象建立一個新的名為value的節點,然後用文檔的appendChild方法将節點添加到文檔中。

  在建立所有新的節點後,SaveValues調用DOMDocument's save方法存儲新的xml檔案。

  注意這個新的檔案已經覆寫了舊檔案,使用DOMDocument對象無法部分改變XML檔案,可以加載XML檔案,然後修改其中一部分,然後儲存檔案,但原檔案将被完全覆寫。這是一個小的缺陷,但在這時可以使用其它程式進行修改。

  List1的最後一部分是CreateNode子程式,CreateNode 為父節點建立一個新節點并同時給這個節點指派。在這個子程式中首先引用一個DOMDocument對象,然後使用該對象的createElement方法建立一個新的節點。

  createNode方法設定節點的text屬性,然後将節點作為子節點添加到父節點中。

  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 程式    雖然每個人都化了很大的精力去處理xml文檔,使他們看上更容易些,但xml工具一般都忽略了那些使xml文檔結構明顯的空白和縮進,xml解析器也同樣忽略縮進和空白。    不幸的是我們例子也同樣忽略了這些縮進和空白,SaveValues建立了一個象下面那樣的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>    VB.NET中包括了文本寫入類,可以XML文檔規定格式。但MSXML重沒有這種功能,是以如果需要以一種清晰的格式儲存XML檔案,隻能另行添加它的格式。    List2列出了程式SaveValuesIndented使用的代碼,SaveValues子程式與上面例子中講的幾乎完全相同,但他在建立value節點後同時給XML文檔建立了一個<value>标記的新行。    然後SaveValues 調用CreateNode建立一個新的資料節點,但在這裡它傳遞給CreateNode一個新的參數,這個參數表示這個新節點的縮進方式。    CreateNode  ' 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(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 程式    雖然每個人都化了很大的精力去處理xml文檔,使他們看上更容易些,但xml工具一般都忽略了那些使xml文檔結構明顯的空白和縮進,xml解析器也同樣忽略縮進和空白。    不幸的是我們例子也同樣忽略了這些縮進和空白,SaveValues建立了一個象下面那樣的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>    VB.NET中包括了文本寫入類,可以XML文檔規定格式。但MSXML重沒有這種功能,是以如果需要以一種清晰的格式儲存XML檔案,隻能另行添加它的格式。    List2列出了程式SaveValuesIndented使用的代碼,SaveValues子程式與上面例子中講的幾乎完全相同,但他在建立value節點後同時給XML文檔建立了一個<value>标記的新行。    然後SaveValues 調用CreateNode建立一個新的資料節點,但在這裡它傳遞給CreateNode一個新的參數,這個參數表示這個新節點的縮進方式。    CreateNode  ' 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))

' Add a new line.

parent.appendChild parent.ownerDocument.createTextNode(vbCrLf)

  結論

  本文僅僅揭示XML程式設計的表面,本文的例子中的涉及隻是非常簡單的XML檔案,但你可以使用使用本文揭示的技術做更多的事情,比如配置設定、表機關置、以及其他資訊。XML已經向前更進一步的發展了,有了更複雜的資料層次。對于更複雜的資料結構,在運作時可以更容易的使用MSXML對象來存取XML檔案

本文轉自 夢在旅途 部落格園部落格,原文連結:http://www.cnblogs.com/zuowj/archive/2012/12/11/2813730.html  ,如需轉載請自行聯系原作者