2008年12月3日 星期三

自訂XML設定檔案1-1

RunPC 110期:在.NET上保存應用程式設定(二)


在這.NET上保存應用程式系列的文章中,我們第一篇所提及的是怎麼利用系統所提供的DynamicProperties機制來運作保存應用程式設定,我們依順為各位介紹了 (1) 如何設定預設的動態屬性步驟:怎麼樣利用Visual Studio.NET IDE中的屬性視窗,設定控制項物件的DynamicProperties屬性來完成簡易的保存應用程式設定,不用撰寫任何程式碼,全由系統自動產生相關的程式碼。 (2) 如何在專案中設定非預設的動態屬性設定即為自訂的動態屬性設定:若於Visual Studio.NET IDE中的屬性視窗中找不到該控制項物件的DynamicProperties屬性選項,我們可以於Sub New程序內模擬InitializeComponent內的作法利用AppSettingsReader類別來讀取設定檔案的內容值,但如此做只解決了可讀取非系統預設的屬性或自訂的特殊屬性值,卻依舊不能達到可動態保存應用程式設定值於下次啟用或使用應用程式時仍保留其狀態值的需求。 (3) 如何在執行時期保留動態屬性值:很不幸地,以上二點仍舊脫離不了只能唯讀的問題,尤其是ConfigurationSettings的方法,在這兒我們利用一點小技巧說明怎樣利用.NET所提供的System.Xml名稱空間下的相關類別來維護XML(即app.config)的資料,以達成可讀可寫的動態屬性儲存設定。以上詳細的說明資料及作法請見上期【在.NET上保存應用程式設定(一):DynamicProperties】。本期我們將重點放置於:如何在.NET上利用自訂的XML設定檔案來保存應用程式相關的設定值,當然在各應用系統中我們都有可能要保存自已所屬的應用程式設定,如:A_Ap系統透過A_Config檔案連結到A_DB資料庫;B_Ap系統透過B_Config檔案連結到B_DB資料庫…等。當然我們可以在各系統中獨自加入讀寫自訂的XML設定檔案來保存應用程式的相關設定值,但是這種作法是最不好的作法,會造成後續程式碼維護不易、版本控制不易…等種種問題,凡架構在.NET CLS(Common Language Specification)上的各種程式語言皆以物件導向為主,是故較佳的作法是以撰寫共通自訂XML設定檔案類別(Class)元件的方式來產生,以下就讓我們開始一窺全貌。

自訂設定檔案標準命名規則
讀者若於.NET相關設定檔案議題有所涉略或已閱讀過筆者前一篇文章,那各位應了解.NET在視窗應用程式的設定檔案為『app.config』與『執行檔案名.exe.config』和其二者的差異與使用時機,而.NET 在Web應用程式的設定檔案為應用程式目錄下的『web.config』這是.NET對應用程式設定檔案的命名規則,而我們自訂的XML設定檔案將其命名規則標準統一化,不論是Web或視窗的應用程式系統皆以『執行檔案名稱.xml』來加以命名,其預設所存放的路徑為該執行檔所在的目錄下,當然為了該共通類別元件更俱彈性化,我們將在該類別中建立多個建構子(Constructor),以傳入所屬應用程式設定檔案的路徑,以利在非預設路徑下作業。至此我們已完成自訂設定檔案命名規則和所在路徑的規劃,接下來讓我們針對自訂XML設定檔案的內容加以分析。

規劃自訂XML設定檔案的結構
在規劃自訂XML設定檔案的結構之前讓我們先來看看一般INI檔呈現的格式內容:

[Section1]
Key1=Value1
Key2=Value2
[Section2]
Key3=Value3
Key4=Value4
……

上Section1與Section2為二組設定,其內各有鍵值成對各二對,如今若要將其轉成自訂XML設定檔案格式可以轉為以值為基礎(Value-Based)的XML格式設定檔案內容或以屬性為基礎(Attribute-Based)的XML格式設定檔案內容。


以值為基礎(Value-Based)的XML格式設定檔案內容



以屬性為基礎(Attribute-Based)的XML格式設定檔案內容

以上二種以值為基礎的XML格式或以屬性為基礎的XML格式皆可成為自訂的設定檔案,但筆者建議以後者來當設定檔案格式的內容,因為它可以使用較簡單的程式碼來處理該XML,且該XML的格式呈現也比較簡潔易讀。
註:不論採用何種XML設定檔案格式,我們僅記XML是大小寫有關的,且必需有一個根節點,這兒的根節點為ApplicationSettings…等符合XML well-formed。

建立共通XML設定檔案元件
在確立自訂XML設定檔案命名規則與該XML設定檔案的內容結構是採用以屬性為基礎的XML格式設定檔案內容後,我們可以著手建立共通XML設定檔案元件,其詳細步驟如下:

1、 開啟『Microsoft Visual Studio.NET』,於啟始頁(Start Page)內的專案(Projects)點選新增專案(New Project)打開新增專案對話盒。
2、 於專案類型(Project Types)內選擇Visual Basic專案(Visual Basic Projects)(以VB.NET為例),再於範本(Templates)內選擇類別庫(Class Library)的專案類型,在名稱(Name)的地方輸入專案名稱為ProXMLSettings(圖一),點選確定建立新的類別庫專案。

(圖一)建立VB.NET類別新專案
3、 系統預設會為新的類別專案產生一個Class1.vb的檔案,於方案總管(Solution Explorer)內選擇該Class1.vb選項後修改屬性視窗(Properties)內的檔名(FileName)屬性為易記的名稱ClsSettings.vb,再將程式碼視窗內的預設類別名稱Class1修改為ClsSettings。
4、 Imports相關的NameSpace,於ClsSettings類別名稱之前

Imports System.Xml
Imports System.Environment

Imports System.Xml是為了用於讀取維護自訂XML設定檔,而Imports System.Environment是為了要取得目前目錄的位置(XML設定檔案目錄位置)。
5、 於ClsSettings類別內宣告類別成員變數
>"
Private m_StrXMLFilePath As String
Private m_XmlDocument As XmlDocument

m_StrXMLFilePath的類別成員變數是用來存放完整XML設定檔案路徑;m_XmlDocument是用來存放該類別的XmlDocument,以利後續的XML存取維護。
6、 建立類別建構式
如前面『自訂設定檔案標準命名規則』內所述,我們可以建立多個類別建構式,在此我們建立二個建構式,其一為Public Sub New(ByVal AppName As String),只傳入應用程式的名稱,而路徑採預設值為該應用程式執行檔所在位置(CurrentDirectory為取得並設定目前目錄的完整路徑;也就是,啟動這個處理序的目錄。);其二建構式為Public Sub New(ByVal AppName As String, ByVal SettingsPath As String),它的SettingsPath參數是用來傳入完整的XML設定檔案路徑位置。

'第一個類別建構式:採用應用程式所在目錄路徑
Public Sub New(ByVal AppName As String)
XMLFilePath = CurrentDirectory & "\" & AppName & ".xml"
OpenXMLFile()
End Sub

'第二個類別建構式:可借由傳入完整的XML設定檔案路徑(SettingsPath)
Public Sub New(ByVal AppName As String, ByVal SettingsPath As String)
' SettingsPath.IndexOf("\") > 0用以判斷是否函有”\”,有表完整路徑,無表只有檔名
If SettingsPath.IndexOf("\") > 0 Then
XMLFilePath = SettingsPath
Else
XMLFilePath = CurrentDirectory & "\" & SettingsPath
End If
OpenXMLFile()
End Sub

'XMLFilePath類別屬性:用於儲存XML設定檔案完整路徑
Public Property XMLFilePath() As String
Get
Return m_StrXMLFilePath
End Get
Set(ByVal Value As String)
m_StrXMLFilePath = Trim(Value)
End Set
End Property

'載入XML設定檔案
Private Sub OpenXMLFile()
Dim XmlTR As New XmlTextReader(XMLFilePath)
m_XmlDocument = New XmlDocument()
m_XmlDocument.Load(XmlTR)
XmlTR.Close()
XmlTR = Nothing
End Sub

在OpenXMLFile我們使用了XmlTextReader物件來載入XML設定檔案。至此我們已經完成類別建構式、保存XML設定檔案路徑與載入XML設定檔,接下來讓我們看看如何利用XPath運算式來取得XML設定檔內我們所要的值。
7、運用XPath查詢XML設定內容值
XPath是W3C(World Wide Web Consortium)所制訂的一項標準,我們可將它視為在XML內的SQL查詢語言,它主要的目的就是描述節點相對其它節點的位置,經由它我們可以簡易地從XML檔案中篩選出我們所要的資料值;如今我們要利用XMLDocument物件的SelectSingleNode方法傳入XPath運算式來取得XMLNode物件,或經由SelectNodes方法來取得XMLNodeList物件,在這兒我們使用SelectSingleNode方法來取得XMLNode物件,其中的XPath運算式或稱為XPath位置路徑(Loacation Path)為"//Section[@Name='SectionName']"這表示查詢根節點下所有Section元素內含元素屬性Name的值為SectionName的所有節點,
而”descendant::Key[]”表取得xnSection節點下的子節點,當然若您熟悉XPath位置路徑語法,這其中就可以有許許多多延伸的使用方式了,將Section替換成Age,Name替換成Field而SectionName替換成'年齡'…等就可以取得上篇文章內的所述的消貸系統融資審核表XML設定檔,內的資料,詳細的XPath請參考http://www.w3.org/TR/xpath。下表(表一)列出XPath位置路徑相關的運算子:

(表一) XPath位置路徑相關的運算子

'XML型態列舉
Public Enum XmlTypes
XmlString = 0
XmlInteger = 1
XmlBoolean = 2
End Enum
'經由XPath取得XML設定值
Public Function GetXmlSetting(ByVal SectionName As String, ByVal KeyName As String, Optional ByVal DefaultValue As Object = NullValue, Optional ByVal XmlType As XmlTypes = XmlTypes.XmlString) As Object
Dim sKeyValue As Object
Dim xnSection As XmlNode
Dim xnKey As XmlNode
xnSection = m_XmlDocument.SelectSingleNode("//Section[@Name='" & SectionName & "']")
If xnSection Is Nothing Then
sKeyValue = NullValue
Else
xnKey = xnSection.SelectSingleNode("descendant::Key[@Name='" & KeyName & "']")
If xnKey Is Nothing Then
sKeyValue = NullValue
Else
sKeyValue = xnKey.Attributes("Value").Value
End If
End If
xnKey = Nothing
xnSection = Nothing
Select Case XmlType
Case XmlTypes.XmlInteger
If sKeyValue = NullValue Then
sKeyValue = DefaultValue
Else
Try
sKeyValue = CType(sKeyValue, Integer)
Catch
sKeyValue = 0
End Try
End If
Case XmlTypes.XmlBoolean
If sKeyValue = NullValue Then
sKeyValue = DefaultValue
Else
Try
sKeyValue = CType(sKeyValue, Boolean)
Catch
sKeyValue = False
End Try
End If
Case Else
If sKeyValue = NullValue Then sKeyValue = DefaultValue
End Select
Return sKeyValue
End Function

我們建立了XmlTypes的列舉用來確立所存放在XML設定檔案內的值的資料型態,在類別的GetXmlSetting函數成員中我們傳入四個參數,前二個參數為必要參數,為組合XPath位置路徑,而後二者為選項參數DefaultValue參數表若查詢XPath位置路徑無該節點值時,將傳回的預設值,最後一個參數XmlType是自訂的列舉,表要取得的資料型態,至此我們已可以經由傳入元素名稱和屬性值來取得XML設定值,接下來讓我們看看怎麼將值存回XML設定檔案中。

8、回存設定值
因為我們在規劃自訂XML設定檔案的結構中已確立以屬性為基礎(Attribute-Based)的XML格式設定檔案內容,節點名稱為Section和Key,而屬性名稱為Name和Value是故,儲存程序的參數只要傳入SectionName節點名和KeyName屬性名和Setting屬性設定值即可。

Public Sub SaveSetting(ByVal SectionName As String, ByVal KeyName As String, _
ByVal Setting As Object)
Dim xnSection As XmlNode
Dim xnKey As XmlNode
Dim xnAttr As XmlAttribute
If m_XmlDocument.DocumentElement Is Nothing Then
m_XmlDocument.LoadXml("" & _
ControlChars.CrLf & "" & ControlChars.CrLf & "")
End If
xnSection = m_XmlDocument.SelectSingleNode("//Section[@Name='" & SectionName & "']")
If xnSection Is Nothing Then
xnSection = m_XmlDocument.CreateNode(XmlNodeType.Element, "Section", "")
xnAttr = m_XmlDocument.CreateAttribute("Name")
xnAttr.Value = SectionName
xnSection.Attributes.SetNamedItem(xnAttr)
Dim xnRoot As XmlNode = m_XmlDocument.DocumentElement
xnRoot.AppendChild(xnSection)
xnRoot = Nothing
End If
xnKey = xnSection.SelectSingleNode("descendant::Key[@Name='" & KeyName & "']")
If xnKey Is Nothing Then
xnKey = m_XmlDocument.CreateNode(XmlNodeType.Element, "Key", "")
xnAttr = m_XmlDocument.CreateAttribute("Name")
xnAttr.Value = KeyName
xnKey.Attributes.SetNamedItem(xnAttr)
xnAttr = m_XmlDocument.CreateAttribute("Value")
xnAttr.Value = Ctype(Setting,String)
xnKey.Attributes.SetNamedItem(xnAttr)
xnSection.AppendChild(xnKey)
Else
xnKey.Attributes("Value").Value = Setting
End If
m_XmlDocument.Save(XMLFilePath)
xnKey = Nothing
xnSection = Nothing
End Sub


程式碼說明:m_XmlDocument.DocumentElement判斷該文檔的根元素是否存在,不存在的話這我們建立一個新的,而xnSection = m_XmlDocument.SelectSingleNode("//Section[@Name='" & SectionName & "']")經由XPath位置路徑找出節點,若該節點未找到的話建立一個Section節點,且加入一屬性Name其值為SectionName,再將該節點加入根節點內,至此建立一個新的Section節點,接下來要設其Section節點下的子節點Key與其屬性值,xnKey = xnSection.SelectSingleNode("descendant::Key[@Name='" & KeyName & "']") 經由XPath位置路徑找出節點,當然同上若未找到該節點建立一個新節點Key,和建立該節點的Name、Value屬性,接下來再設定值到Name、Value屬性上xnAttr.Value = KeyName 、xnKey.Attributes("Value").Value = Setting,最後將修改過的XML設定值回存到檔案上m_XmlDocument.Save(XMLFilePath)。

沒有留言:

加入書籤: MyShare HemiDemi Baidu Google Bookmarks Yahoo! My Web PChome Del.icio.us Digg technorati furludn bookmark 其他更多書籤

BOOKS:New and Upcoming