Presentation is loading. Please wait.

Presentation is loading. Please wait.

第二十二章 C++ Builder上的XML應用

Similar presentations


Presentation on theme: "第二十二章 C++ Builder上的XML應用"— Presentation transcript:

1 第二十二章 C++ Builder上的XML應用
XML(eXtensible Markup Language)可擴展標示語言是最近興起的標示語言,由於使用方便而逐漸廣泛應用在資料的交換與表示上,因此,Borland在C++ Builder 6上加入了對XML的支援,讓一般使用者可以透過更簡便的方式來使用XML格式的檔案,或是透過XML檔案做些額外的應用。

2 大綱 21-1 XML簡介 21-2 XML基本存取元件的使用 21-3 使用Data Binding輔助工具
21-4 MyBase個人資料庫 21-5 MyBase進階應用

3 22-1. XML簡介 XML是eXtensible Markup Language的縮寫,中文譯為"可擴展標示語言"或"可延伸性標示語言",由W3C(World Wide Web Consortium)所制定,並於 1998 年 2 月成為推薦規格,該語言和HTML同為SGML所衍伸出來的語言,而 SGML(全名為Standard Generalized Markup Language)是國際標準組織(ISO)於1986年審核通過的一種文字及文件國際標準,不過卻因格式複雜、文件開發不易和解讀困難等缺點而一直無法廣泛被使用於企業界或是網路上,但簡化後的版本如HTML和XML等卻被廣泛使用,其中HTML成為網頁格式的標準而普遍使用在網路上,而XML則繼HTML後成為目前最受矚目的標記語言。

4 22-1. XML簡介 HTML因為簡單易學而廣泛被使用,但相對的也有其缺點而限制了它的使用彈性,因此當寬頻、無線網路環境逐漸成為主流時,它的困境也就越來越明顯了,底下為幾個HTML的缺點: 文件內容與顯示格式無法分離,導致HTML的內容無法有效的轉移到其他平台上,因為顯示格式的安排可能受限於使用的環境,如手機和PDA上由於螢幕大小的限制便無法像瀏覽器般顯示過多的美工排版與內容,而必須對排版方式做些修正,此外,傳統HTML檔案亦無法作為顯示風格隨使用者不同而變的個人化網頁服務,但這些在XML檔案下皆能輕易完成,如手機上使用的WAP便是一種XML檔案。

5 22-1. XML簡介 固定標籤限制了使用彈性。HTML的標籤決定於W3C訂定的版本,也就是所有的標籤名稱在每一版本的HTML規格中是固定的,如下圖即為HTML的標準格式,並無法對標籤名稱進行修改,且每個標籤所允許的屬性亦是固定的,因此,這些固定名稱和屬性就限制了HTML使用的彈性,譬如瀏覽器和手機在內容呈現上的定義可能不同,自然HTML定的標籤和屬性名稱對於手機來說就不一定適用。

6 22-1. XML簡介 相對於上述HTML所面臨的困境,XML檔皆找到合適的解決方案,而這正是XML能興起的主因。
HTML文件主要著重在顯示格式的設定,而非文件內容的紀錄,因此並沒有完整的架構來紀錄文件的內容,但對於企業或是資料處理來說,文件的內容才是處理的重心,譬如對於一份訂單來說,企業所在意的並不是訂單有多漂亮,而是訂單的商品內容和數量,但從HTML檔案中卻無法清楚的了解訂單的項目和數量,因此並不適合作為內容紀錄和資料處理的依據,更不能作為資料交換的依據,此外,結構過於鬆散亦增添企業內對HTML檔案內容進行處理的困難,譬如<HTML>這個標籤需要對應的結尾標籤</HTML>,但<Br>卻不需要,而這沒有對稱性的架構卻大大增加處理的困難。 相對於上述HTML所面臨的困境,XML檔皆找到合適的解決方案,而這正是XML能興起的主因。

7 22-1. XML簡介 XML具備底下幾個特性,而這些特性正式其優於HTML的地方。
完整的階層架構:也就是XML為一個Well-Formed文件,而Well-Formed文件的規格有二: 所有的標籤名稱皆需要對應一個結尾標籤,如<HTML>標籤對應</HTML>或當標籤間資料為空時以<HTML/>代表起始標籤和結尾標籤,底下均為標準的標籤用法。

8 22-1. XML簡介 標籤和結尾標籤必須在同一階層,也就是所有的標籤以巢狀迴圈形式出現,內層的標籤其結尾標籤必定在內層出現,不允許在外層出現的情形,下面為正確範例和錯誤範例的比較。 任意階層數的巢狀結構:只要標籤和對應的結尾標籤符合巢狀形式出現,則並沒有限制每個標籤內所允許的階層數目,因此大大增加應用的彈性。 允許對檔案格式進行驗證:透過驗證檔案的指定,可對XML內容進行驗證的動作,檢查各標籤內容是否被驗證檔案所允許,以確保檔案內容在編輯修改時能保持其一致性。

9 22-1. XML簡介 底下為一個基本的XML檔案範例。在範例中,我們透過自訂標籤來儲存員工的基本資料。

10 22-1. XML簡介 從上面檔案中可看到一份XML檔案根據內容用途可簡單劃分為四區:文件宣告區、文件型態定義區、排版樣式定義區和文件內容區,簡述如下: 文件宣告區: 文件宣告區為一份XML文件所不可少的部分,其中的第一列必須宣告此文件為一個XML檔案和指定其版本訊息,除此,還可額外指定其使用的編碼方式或是宣告是否有其他檔案配合使用,底下均為合法的XML宣告範例: 最基本的XML宣告 <?xml version="1.0" ?>

11 22-1. XML簡介 指定XML的編碼方式為Big5繁體中文。 指定XML的編碼方式外,還指定該XML檔案為單獨存在,並沒有引用別的檔案內容。 此外,在基本的宣告之後,還可以選擇性的對文件型態和排版樣式進行定義,其中的文件型態用來規範XML文件的內容,而排版樣式則定義XML文件在顯示時的呈現方式。 <?xml version="1.0" encoding="Big5"?> <?xml version="1.0" encoding="Big5" standalone="yes">

12 22-1. XML簡介 文件型態定義 前面曾經介紹XML的優點在於能提供文件內容驗證的機制,而這個驗證的機制主要是透過對文件型態的定義來達成。該文件型態定義為一個DTD(Document Type Definition)檔案,透過該檔案我們可以對XML文件進行如下的定義: 文件的階層架構。 標籤的內容和型態。 標籤屬性。

13 22-1. XML簡介 底下為一個簡單的DTD範例,在這個範例中我們對前面的myemployee.xml檔案的內容進行定義。
myemployee.dtd檔案內容 <?xml version="1.0" encoding="Big5"?> <!ELEMENT Employee (Person*)> <!ELEMENT Person (Name, EmpId, Salary, PhoneNo+, PhoExt, HireDate)> <!ELEMENT Name (#PCDATA)> <!ELEMENT EmpId (#PCDATA)> <!ELEMENT HireDate (#PCDATA)> <!ELEMENT PhoExt (#PCDATA)> <!ELEMENT PhoneNo (#PCDATA)> <!ELEMENT Salary (#PCDATA)>

14 22-1. XML簡介 上述DTD檔案限定了myemployee.xml檔案的文件型態如下:
Employee標籤可含有數個Person子標籤。 Person標籤內含Name、EmpId、Salary、PhoneNo、PhoExt和HireDate標籤,其中PhoneNo標籤的數目至少一個,但其他標籤在Person標籤下只能出現一次。 Name、EmpId、Salary、PhoneNo、PhoExt和HireDate標籤內容由可被剖析的文字資料所構成,其中PCDATA為Parser Character Data的縮寫。 在驗證過程中,若檔案內容不符合DTD所指定的規則時,將產生錯誤的訊息。

15 22-1. XML簡介 除了透過DTD檔案進行驗證外,我們亦可透過XML Schema的使用來達到同樣的目的。XML Schema為DTD後所提出來用以定義XML文件的標準,之所以會被提出且逐漸取代DTD檔案在於其有底下幾個優點: 和XML文件的語法相同:從上面的DTD檔案示範中可以發現,DTD的語法和XML檔案的語法是完全不同的,因此,學習DTD語法將成為使用者額外的負擔,而XML Schema改進這個缺點,使用和XML文件相同的語法。 提供更彈性的文件標準設定:DTD語法在文件的定義上,提供了過少的資料型態和設定彈性,因此,對於複雜的文件定義,往往無法如使用者所想進行規範,而這也是XML Schema推出的主因之一。在XML Schema中,不但提供了多樣的資料型態設定,還提供對範圍設定和條件設定的支援,因此更能滿足不同使用者的需求。

16 22-1. XML簡介 我們透過簡單的圖表說明兩者間的差異:
比較 DTD XML Schema 語法 承襲SGML的DTD而來,因此有屬於自己的一套語法規範,和XML的語法內容完全不同。 完全依照XML文件的語法標準。本身即為一個XML檔案。 資料型態 只提供CDATA、ENUMERATED、NMTOKEN、NMTOKENS、ID、IDREF、ENTITY、ENTITIES和NOTATION等十種資料型態。 除了DTD所提供的型態外,而提供如Date、Boolean、Float、Double和Integer等數十種的資料型態。 格式設定 不支援。 允許對資料格式進行設定,如ddd限制資料格式為三位數的數字。

17 22-1. XML簡介 範圍設定 不支援。 允許設定資料的範圍,如可限制數值輸入介於100-200間。 自訂型態 允許自定資料型態。
比較 DTD XML Schema 範圍設定 不支援。 允許設定資料的範圍,如可限制數值輸入介於 間。 自訂型態 允許自定資料型態。 物件概念 含有物件的概念。對於資料型態和結構提供繼承等功能。 複雜度 使用彈性 更詳細的XML Schema說明請參考坊間XML相關書籍,在此,僅提供相對於myemployee.dtd檔案的XML Schema檔案供讀者參考,兩者同樣可作為myemployee.xml檔案驗證之用。

18 22-1. XML簡介 myemployee.xsd檔案
<?xml version="1.0" encoding="Big5"?> <xs:schema xmlns:xs=" > <xs:element name="EmpId"> <xs:simpleType> <xs:restriction base="xs:string"> <xs:length value="7"/> </xs:restriction> </xs:simpleType> </xs:element> <xs:element name="Employee"> <xs:complexType> <xs:sequence> <xs:element ref="Person" maxOccurs="unbounded"/> </xs:sequence> </xs:complexType>

19 22-1. XML簡介 <xs:element name="HireDate" type="xs:date"/>
<xs:element name="Name"> <xs:simpleType> <xs:restriction base="xs:string"/> </xs:simpleType> </xs:element> <xs:element name="Person"> <xs:complexType> <xs:sequence> <xs:element ref="Name"/> <xs:element ref="EmpId"/> <xs:element ref="Salary"/> <xs:element ref="PhoneNo"/> <xs:element ref="PhoExt"/> <xs:element ref="HireDate"/> </xs:sequence> </xs:complexType>

20 22-1. XML簡介 <xs:element name="PhoExt"> <xs:simpleType>
<xs:restriction base="xs:string"> <xs:length value="5"/> </xs:restriction> </xs:simpleType> </xs:element> <xs:element name="PhoneNo"> <xs:minLength value="0"/> <xs:maxLength value="10"/> <xs:element name="Salary" type="xs:int" default="30000"/> </xs:schema>

21 22-1. XML簡介 上述的程式碼相較於DTD 檔案略為複雜,但卻能提供更詳細的文件定義。至於XML Schema文件定義的引用方式則如下所示:

22 22-1. XML簡介 排版樣本定義 除了對文件內容的定義外,XML檔案還可就顯示的格式進行定義,也就是所謂的內容和排版分離。如此,XML檔案就能專注於對內容的紀錄,而把排版(或呈現)的工作交給排版樣本來定義。XML檔案的排版樣本定義稱為XSL,本身亦為一遵循XML語法的XML檔案。底下為myemployee.xml檔案的簡單排版樣式定義: <?xml version="1.0" encoding="Big5"?> <xsl:stylesheet xmlns:xsl=" <xsl:template match="/"> <html> <head><title>員工基本資料</title></head> <body> <table border="1" > <tr> <td>員工編號</td> <td>員工姓名</td> <td>電話號碼</td>

23 22-1. XML簡介 <td>公司分機</td> <td>薪水</td>
</tr> <xsl:for-each select="Employee/Person"> <tr> <td><div style="color:blue"><xsl:value-of select="EmpId"/></div></td> <td><div style="background:yellow"><xsl:value-of select="Name"/></div></td> <td><div style="font-weight:bold"><xsl:value-of select="PhoneNo"/></div></td> <td><div style="font-weight:bold"><xsl:value-of select="PhoExt"/></div></td> <td><div style="font-weight:bold"><xsl:value-of select="Salary"/></div></td> <td><div style="font-weight:bold"><xsl:value-of select="HireDate"/></div></td> </xsl:for-each> </table> </body> </html> </xsl:template> </xsl:stylesheet>

24 22-1. XML簡介 此檔案轉換myemployee.xml為HTML中的表單形式對內容進行呈現。簡單說來,XSL檔案所做的事為把XML中對應的標籤依照XSL指定的內容進行置換的工作,因此,除了對排版內容進行定義外,還可透過對標籤的置換達到文件交換的功用。 右邊為myemployee.xml檔案有無搭配XSL檔案在瀏覽器中的差別。 指定XSL檔案 沒有XSL檔案

25 22-1. XML簡介 文件內容區 XML相關檔案間的關係
文件內容區即XML文件儲存內容的地方,透過自訂標籤的方式配合Well-Formed的格式即能表示XML文件的內容,若該份文件指定DTD或是XML Schema檔案對內容進行定義,則整份XML文件還必須符合DTD或XML Schema中的定義。 XML相關檔案間的關係

26 22-2. XML基本元件的存取使用 常用的 XML文件存取方法有兩種:DOM和SAX
DOM:全名為Document Object Model。存取XML文件的方法為把整份XML文件先載入到記憶體中形成一個樹狀結構,再透過對個別樹狀節點的控制來達成存取文件的目的,因此,效率會比較差,但對XML文件的存取卻比較方便。 SAX:全名為Simple API for XML。該方法僅載入部分XML文件內容進行分析,進而讀取XML文件內容,由於每次的載入動作僅讀取部分的XML文件內容而非整份XML文件,因此在使用效率上比DOM來的佳,但卻有操作不易等缺點。 在C++ Builder中則使用DOM方法作為存取XML檔案的依據。透過不同廠商實作的DOM Interface便可對XML文件進行存取的動作。然而,DOM Interface的定義十分複雜,在使用上極不方便,為此,C++ Builder封裝Microsoft所實作的MS DOM為XMLDocument元件以方便使用者對XML元件存取的動作,而透過XMLDocument元件的輔助,存取XML文件內容也變得簡單許多。

27 22-2-1. XMLDocument元件 XMLDocument元件存在於元件樣版中的Internet頁次
設定DOMVendor屬性:透過該屬性選擇不同廠商所實作的DOM介面。由於Windows作業系統本身即提供了DOM介面的支援(MS DOM),所以可直接設定該屬性值為MSXML即可。 指定讀入的XML文件:透過Filename屬性指定XML檔案或是以XML屬性讀入TStrings型態的內容。諸如Memo元件的Lines屬性或是ListBox元件的Items屬性皆為TStrings型態。

28 XMLDocument元件 設定分析方法的選項:透過ParseOptions屬性設定DOM分析XML內容的方法。此屬性的內容取決於DOMVendor屬性所設定的DOM實作廠商,而預設的MSDOM則提供了以下幾個子屬性:poResolveExternals、poValidateOnParse、poPreserveWhiteSpace和poAsyncLoad。各子屬性功能簡述如下: 子屬性 功能敘述 poResolveExternals 外部相關的定義在Parse時是否同時考慮,所謂的外部定義包括namespaces、DTD external subsets和external entity references。 poValidateOnParse 設定分析(Parse)文件內容時,是否去檢查該文件有無符合DTD或XML Schema檔案的限制。 poPreserveWhiteSpace 設定是否去掉XML文件中的空白符號。 poAsyncLoad 設定是否允許分次進行文件分析的工作。分次分析文件的工作能加速處理XML文件的速度,但卻可能發生處理節點尚未被XMLDocument分析的錯誤。

29 XMLDocument元件 設定Active屬性對文件內容進行分析:在設定Active屬性為True後即可透過XMLDocument元件內的方法對XML內容進行讀取的動作。由於XMLDocument元件以樹狀結構儲存載入的XML文件,所以對XML文件存取的第一步便是利用內建的DocumentElement屬性回傳文件的進入點,而此回傳值為C++ Builder為了簡化存取流程所自訂的IXMLNode介面(宣告型態為_di_IXMLNode)。透過IXMLNode介面的回傳即可對此節點內的屬性值或子節點進行內容讀取、新增和刪除的動作。底下為C++ Builder為了簡化XML文件存取所提供的幾個介面 介面 宣告型態 敘述 IXMLDocument _di_IXMLDocument 該介面表示一份文件。 IXMLNode _di_IXMLNode 該介面表示XML文件上的一個節點。 IXMLNodeList _di_IXMLNodeList 該介面表示XML文件中同一階層的所有節點。 IXMLNodeCollection _di_IXMLNodeCollection 該介面表示同一型態的子節點集合。

30 22-2-1. XMLDocument元件 利用上面這些介面配合XMLDocument元件所提供的函式即可存取 XML文件內容。
新增節點 刪除節點 _di_IXMLNode newPerson=XMLDocument1->DocumentElement->AddChild("Person"); _di_IXMLNode personInfo; personInfo=newPerson->AddChild("Name"); //新增Person內的Name子標籤 personInfo->Text=LabeledEdit2->Text; //指定Name標籤的內容 _di_IXMLNode employee=XMLDocument1->DocumentElement; employee->ChildNodes->Delete(employee->ChildNodes->Count-1);

31 22-2-1. XMLDocument元件 讀取節點 結合上面所述,底下透過實例說明的方式來示範如何對XML文件進行存取的動作。
//讀取employee內的第一筆資料 AnsiString temStr; _di_IXMLNodeList personList=XMLDocument1->DocumentElement->ChildNodes; _di_IXMLNodeList person= personList->Nodes[1]->ChildNodes; for(int i=0;i<person->Count;i++)//依序顯示person節點內的子節點內容 { temStr=person ->Nodes[i]->NodeName+":" +person->Nodes[i]->Text; ShowMessage(temStr); }

32 22-2-1. XMLDocument元件 【操作實例22-1】XML文件的存取
在本實例中,我們讀取上一小節的myemployee.xml檔案,並允許對該檔案進行新增資料的動作。 開啟新專案,新增元件如下圖所示,其中XMLDocument元件位於元件樣版中的Internet頁次。

33 22-2-1. XMLDocument元件 設定XMLDocument元件屬性如下:
在【載入】、【新增】和【儲存】三個按鈕的OnClick事件和表單的OnShow事件中加入對應的程式碼。Main.cpp程式碼 執行程式。 屬性 元件 Name Active DOMVendor FileName XMLDocument XMLDocument1 True MSXML myemployee.xml

34 22-2-1. XMLDocument元件 【執行結果】
執行程式,按下【載入】按鈕即能讀取XML檔案中的所有內容(如下圖所示),此外,按下【新增】按鈕可就資料進行新增的動作。不過,最後必須按下【儲存】按鈕才能把新增的資料寫入XML檔案中。

35 22-2-1. XMLDocument元件 【實例說明】
XML文件為一個樹狀結構。因此在程式中,我們利用XMLDocument提供的方法來找尋所要存取的樹狀節點,並據此進行新增子節點或是讀取內容的動作。此外,由於DOM的實作方式為把整個XML文件載入到記憶體中進行處理,所以任何的新增或修改動作其實並沒有直接反映到XML檔案中,而是必須透過額外的SaveToFile函式來完成。除此,XMLDocument元件的Options屬性內的doAutoSave子屬性亦能自動儲存變更過的XML檔案。

36 22-3. 使用Data Binding輔助工具 上一小節中,我們利用DOM介面對XML文件進行存取的動作;然而,透過節點找尋的方式對XML標籤進行處理不但麻煩也容易產生錯誤,為此,C++ Builder提供了XML Data Binding這套工具。利用對指定XML文件或結構定義(XML、DTD或XML Schema檔案)產生對應的DOM介面(Interface)來簡化使用者存取XML文件的步驟,也就是透過對介面(Interface)的呼叫即可對指定的節點進行存取的動作,而不再需要一步一步的對樹狀結構進行檢視的動作。底下,我們透過操作實例的說明來教導讀者如何使用Data Binding工具。

37 22-3. 使用Data Binding輔助工具 【操作實例22-2】Data Binding Wizard的使用
透過Data Binding Wizard對myemployee.xsd檔案產生對應的DOM操作介面以對myemployee.xml文件進行存取的動作。 開啟新專案,拖拉Internet頁次中的XMLDocument元件至表單上,並雙擊該元件以彈出Data Binding Wizard對話框如下。在對話框中,我們選擇所要使用的myemployee.xsd檔案。

38 22-3. 使用Data Binding輔助工具 按下上圖的【Next】按鈕進入下一個設定畫面。設定畫面會就所選檔案內容進行分析,並顯示文件的架構如下圖所示。此時,請點選左邊Complex Type下的Employee標籤,並勾取Binding Options中的Document Element Type選項如下圖。

39 22-3. 使用Data Binding輔助工具 按下上圖的【Next】按鈕即可預覽Data Binding Wizard對應myemployee.xsd所產生的介面(Interface)與其內的函式,如下圖所示。在下圖的畫面中,透過左下方的選項可設定是否儲存Data Binding Wizard的設定內容。最後,按下【Finish】按鈕即產生對應介面的程式碼(預設為myemployee.cpp)。往後,透過Include該介面程式碼,即可利用介面(Interface)所提供的方法對符合myemployee.xsd文件定義的XML文件進行存取的動作。

40 22-3. 使用Data Binding輔助工具 回到主表單畫面,設計主表單畫面如下並設定XMLDocument元件的FileName屬性為myemployee.xml。 加入對應三個按鈕的程式片段。Main.cpp程式碼 在Main.h中加入#include “myemployee.h”,其中,myemployee.cpp為介面的內容所在。 執行程式。

41 22-3. 使用Data Binding輔助工具 【執行結果】 【實例說明】
本實例和前一個實例的差別在於本程式透過Data Binding Wizard所產生的介面來對XML檔案進行存取的動作。觀察程式碼內容,可發現本實例的程式較為簡潔、易讀,且也不容易出錯,這正是C++ Builder在XML處理上好用的地方。

42 22-4. MyBase個人資料庫 在第15章中我們曾提及資料庫架構分為Single-Tier、Two-Tier和Multi-Tier三種,而MyBase個人資料庫即為Single-Tier架構的一種,也就是透過Midas.dll的使用以文字檔或XML檔案作為資料儲存的媒介。MyBase個人資料庫相較於另外一種和Two-Tier架構相似但以Access、Paradox等資料庫檔為儲存媒介的Single-Tier架構資料庫程式有不需借助額外連結機制的優點,因此,在本節中我們將透過XML檔案的使用來介紹MyBase個人資料庫。

43 MyBase的檔案來源 MyBase架構下,取代資料庫作為資料集合儲存的檔案在整個程式中扮演了非常重要的角色,並非一般任意格式檔案所能勝任。一般說來,該檔案必須能對資料集合的架構和內容進行描述,而資料集合的架構包括了欄位型態、欄位限制和欄位數目等,至於資料內容則為平常所見到的各筆記錄。在C++ Builder中,常用的MyBase檔案來源有DataPacket(資料封包)和XML檔案兩種。最簡單的DataPacket檔案可透過ClientDataSet(或BDEClientDataSet、SQLClientDataSet)元件的SaveToFile方法呼叫從現存的資料庫中轉換而來,方法如下: 透過ClientDataSet/BDEClientDataSet/SQLClientDataSet元件設定資料集合的來源和CommandText屬性指定所要擷取的資料集合內容。資料提供者依元件的不同,可透過ProviderName、RemoteServer/DBConnection/SQLConnection屬性指定。

44 MyBase的檔案來源 呼叫Open方法或是設定Active屬性接收自資料提供者所傳回的資料集合。 執行SaveToFile方法儲存資料集合內容。該方法可指定所儲存的檔案形式,有binary(dfBinary)、XML(dfXML)和UTF8-based XML(dfXMLUTF8)三種形式可供選擇。 上述步驟產生的檔案極為最基本的Data Packet檔案。下面範例中,我們透過BDEClientDataSet元件的使用來轉換C++ Builder提供的employee.db檔案為一DataPacket形式檔案。

45 22-4-1. MyBase的檔案來源 【範例22-3】轉換Paradox檔案為對應的Data Packet檔案 表單畫面
透過BDEClientDataSet元件的使用轉換Paradox類型的檔案為Data Packet檔案。 表單畫面 屬性 元件 Name DBConnection AliasName DatabaseName DataSet BDEClientDataSet BDEClientDataSet1 Database1 - Database BCDEMOS MyDB DataSource DataSource1

46 MyBase的檔案來源 主要程式碼:Main.cpp 【執行結果】 轉換後的Data Packet檔案 執行畫面

47 MyBase的檔案來源 從轉換後的Data Packet檔案可發現METADATA標籤紀錄資料表所含的欄位名稱和對應的型態,而ROWDATA標籤內則存放資料集合的內容。這樣的架構類似資料庫中資料表儲存資料的方式。 除了透過固定格式的Data Packet檔案對資料進行儲存外,MyBase還允許透過自訂標籤的方式來儲存資料。所謂的自訂標籤XML檔案儲存資料其實是透過一個轉換機制把自訂的XML檔案轉換成標準的Data Packet檔案後再進行處理,而所有處理後的結果在透過轉換的動作從Data Packet格式轉回自訂格式,如此,便完成了自訂格式XML檔案儲存資料的動作。為了讓這樣的一個轉換機制能順利運作,C++ Builder提供了XMLTransform、XMLTransformProvider和XMLTransformClient等元件,除此,還提供了XML Mapper輔助程式幫助進行自訂XML檔案和Data Packet檔案間對應關係的設定動作。下一小節即就XML Mapper的使用方法進行介紹。

48 XML Mapper工具程式 XML Mapper輔助程式的主要功用在提供自訂格式的XML檔案和Data Packet檔案間的轉換,透過標籤的對應讓自訂格式的XML檔案能轉成Data Packet檔案,而Data Packet檔案亦能轉成自訂格式的XML檔案。這樣的轉換效果讓MyBase個人資料庫在儲存媒介的選擇上更為彈性,而不需侷限在單一的Data Packet格式。點選C++ Builder選單中的【Tools】【XML Mapper】即可開啟此一輔助工具。畫面如下圖所示。而為了方便說明起見,我們將以前面所述的myemployee.xml檔案進行說明。

49 XML Mapper工具程式 XML Mapper開啟後的畫面如下圖所示。在畫面中,整個程式分為三個顯示框:左邊顯示XML檔案的內容;右邊顯示Data Packet檔案的內容;而中間的顯示框則設定關於兩者之間的對應關係。每個顯示框又分為兩個不同的頁次可供切換。 兩者對應關係設定 XML檔案內容 Data Packet檔案內容

50 22-4-2. XML Mapper工具程式 底下即透過前面小節中提到的myemployee.xml檔案介紹兩者間的轉換方法:
XML檔案Data Packet檔案 在左邊的顯示框上按下滑鼠右鍵並選擇【Open XML Document】以開啟所要轉換的XML檔案(以myemployee.xml檔案為例)。開啟後將可看到XML檔案的內容以階層形式顯示在左邊的顯示框中。

51 XML Mapper工具程式 在左邊顯示框中的標籤名稱上雙擊滑鼠以選取所要轉換的節點,而雙擊的順序代表轉換後Data Packet檔中欄位儲存的順序。在此,我們選擇Person標籤下的所有節點進行示範,並選擇產生的Data Packet檔案類型為Client DataSet。選擇後的畫面如下圖所示。 選取轉換欄位

52 XML Mapper工具程式 轉換中間顯示框的頁次為Node Properties以檢視每個欄位的屬性設定內容。在顯示框中可針對每個欄位進行個別的設定動作。下面為常見的屬性設定項目。 屬性 敘述 Node Name 設定的節點名稱。 Mapped Name 對應Data Packet檔的欄位名稱。 Data Type 節點的資料型態。 Data Format 當Data Type為時間型態時,設定該屬性以指定字串和日期之間的轉換方式。當Data Type為字串型態時,則設定字串編碼的方式。當Data Type為Binary時,指定多少個bit來表示該資料值。 Max Length 字串型態時,指定轉換後的欄位長度 Value Required 設定該節點是否一定要輸入資料。也就是不允許空白的資料輸入。

53 22-4-2. XML Mapper工具程式 屬性 敘述 Constant Value 該節點的值是否永遠固定。
In Primary Key 該節點轉換後的欄位是否為Primary Key。 Default Value 該節點資料是否有預設值。 Enumeration 若節點的值為固定某些值中的一個,則該屬性可用以設定節點和欄位值之間的轉換關係,如節點為布林值,則可以設定該屬性值為True=Yes False=No指定轉換後的欄位資料。設定格式為NodeValue=FieldValue。 Min Occurs 設定該節點在父節點內的最少出現次數。 Max Occurs 設定該節點在父節點內的最多出現次數。

54 22-4-2. XML Mapper工具程式 設定後的畫面則如下圖所示。在範例中,我們盡量以預設值作為轉換的依據。
Node Properities的設定

55 XML Mapper工具程式 執行選單裡的【Create】【DataPacket from XML】即可產生對應的Data Packet檔案。在右邊的Data Packet顯示框中單擊滑鼠右鍵選擇【Save Datapacket】即可儲存產生的Data Packet檔,畫面如下所示。 儲存轉換後的Data Packet檔案

56 XML Mapper工具程式 在儲存Data Packet對話框中輸入所要儲存的檔名後即完成整個Data Packet檔案的產生工作,而產生的Data Packet檔內容則如下所示。 除了產生已轉換後的Data Packet檔外,XML mapper亦允許產生負責對應XMLData Packet關係的XTR格式轉換檔。

57 22-4-2. XML Mapper工具程式 產生XTR轉換檔
XML Mapper提供的轉換檔格式共有【Datapacket to XML】和【XML to Datapacket】兩種,分別代表Datapacket對XML的轉換和XML 對Datapacket的轉換,而透過Transform Direction的選擇即可指定所產生的轉換檔類型,再按下【Create and Test Transformation】按鈕即可產生轉換結果。在此我們以【XML to Datapacket】作為示範,按下【Create and Test Transformation】即產生對應的XTR轉換檔,並顯示利用該XTR檔案所轉換的內容,如下兩圖所示。 Test Transformation對話框

58 XML Mapper工具程式 關閉Test Transformation對話框後回到XML Mapper的主畫面,在【Create and Test Transformation】按鈕旁單按滑鼠右鍵選擇【Save Transformation】儲存產生的XTR檔後即完成XTR的產生工作,如下圖畫面所示。 產生的XTR檔即可供XMLTransform元件在執行時對自訂的XML檔案進行轉換,以轉成符合Data Packet的格式供ClientDataSet元件使用。如此的MyBase架構即可以自訂的XML檔案作為儲存資料集合的媒介。

59 MyBase資料庫的實作 在了解MyBase資料庫的檔案來源後,底下我們以操作實例來介紹如何使用ClientDataSet元件完成最基本的MyBase資料庫。在該實例中,我們使用myemployee.xml檔案經過XML Mapper轉換後的Data Packet格式檔案作為儲存媒介。 【操作實例22-4】簡易的MyBase資料庫 使用轉換後的Data Packet格式檔案實作簡易的MyBase資料庫。此外,並提供基本的新增、刪除和瀏覽資料功能。

60 22-4-3. MyBase資料庫的實作 開啟新專案,在表單上建立元件如下圖所示。 屬性 元件 Name DataSet
DataSource ClientDataSet ClientDataSet1 - DataSource1 DBGrid DBGrid1

61 22-4-3. MyBase資料庫的實作 在各個按鈕的OnClick事件中加入對應的程式碼如下。Main.cpp程式碼
在ClientDataSet的AfterScroll事件中加入判斷是否顯示為第一筆和最後一筆資料的程式碼。 void __fastcall TForm1::ClientDataSet1AfterScroll(TDataSet *DataSet) { //---判斷是否為資料的第一筆和最後一筆 Button1->Enabled=true; Button2->Enabled=true; Button3->Enabled=true; if(ClientDataSet1->Bof==true) Button2->Enabled=false; Button1->Enabled=false; } else if(ClientDataSet1->Eof==true) Button3->Enabled=false;

62 MyBase資料庫的實作 確定Data Packet類型的XML檔案是否存在。在本例中,myemployee.xml轉換為Data Packet類型的XML檔案名稱為myemployee_dp.xml。 執行程式。

63 22-4-3. MyBase資料庫的實作 【執行結果】
執行程式後,點選【開啟連結】即可顯示檔案(myemployee_dp.xml)中所儲存的資料集合,並執行檢視、新增或刪除的動作。在新增資料的動作中,按下【新增】按鈕即可輸入各欄位資料,按下【確定】完成新增輸入的動作;在刪除資料的動作中,按下【刪除】按鈕即可刪除紀錄指標(DBGrid元件箭頭所指處)所指紀錄。最後,在尚未關閉連結前按下【取消變更】按鈕皆可刪除對資料集合所作的變更。

64 22-4-3. MyBase資料庫的實作 【實例說明】
在本程式中,透過ClientDataSet元件的LoadFromFile讀取Data Packet格式的檔案作為ClientDataSet元件內資料集合的來源,並據此利用資料集合提供的方法,如:First(移到第一筆紀錄)、Prior(前移一筆紀錄)、Insert(新增紀錄)和Delete(刪除紀錄)來完成對資料進行檢視、新增和刪除的動作。有別於一般資料集合元件的地方在於ClientDataSet元件會載入資料集合的所有紀錄於記憶體中,並透過Delta屬性來紀錄對資料集合所作的變更,直到ApplyUpdates或SaveToFile函式呼叫後才把變更的資料存回遠端的資料集合或檔案中。因此,可透過CancelUpdates方法的呼叫來取消Delta中紀錄的變更達到復原的效果。最後,在關閉資料連結時透過SaveToFile的呼叫儲存所作的變更至Data Packet檔案中。

65 22-5. MyBase進階應用 上一小節中,透過 Data Packet類型檔案的使用,我們實作了基本的MyBase程式,而本節中我們將延伸上一小節的應用來強化MyBase的功能,包括Briefcase功能的介紹和以自訂標籤的XML檔案作為儲存媒介。 MyBase的Briefcase功能 MyBase的XML檔案直接儲存

66 22-5-1. MyBase的Briefcase功能
所謂的Briefcase其實就是行動計算的應用。允許應用程式的資料集合來源可根據環境的不同而有所選擇:當和資料庫的連結中斷時,可以把資料轉儲存在本機的檔案中;當和資料庫重新連上線時,所有記錄在本機檔案中的變更可立即反映到資料庫中,讓兩者的資料趨於一致。這樣的應用對需要存取資料庫內資料但又時常無法和資料庫連線的使用者(如業務員)來說十分有用,譬如業務員在公司透過網路抓取資料庫中的客戶資料,然後帶著筆記型電腦和顧客談生意,並對這些從資料庫中讀取的資料進行修改的動作,則其回到公司後透過Briefcase的功能即可自動更新在外面談生意時對資料庫內資料所作的變更,而不再需要額外的人力來確保資料的一致性。 MyBase的Briefcase功能即除了以檔案儲存資料內容外,亦可和遠端的資料庫連結,並反映MyBase中的變更於遠端資料庫中,同時抓取遠端資料庫中的內容達到資料一致的效果。為此,C++ Builder根據資料庫連線方式的不同提供了BDEClientDataSet和SQLClientDataSet兩個元件來輔助這類程式的開發,分別適用於BDE和dbExpress連線環境下。在此,僅透過BDEClientDataSet元件的使用來實作MyBase資料庫的Briefcase功能。

67 22-5-1. MyBase的Briefcase功能
透過BDEClientDataSet元件的使用實作MyBase的程式開發,並增加了和遠端資料庫連結的能力。也就是能把本機端對資料集合的修改傳送到遠端資料庫,並更新資料庫內的資料內容,達到所謂的Briefcase效果。 開啟新專案,設計表單畫面如下圖所示。

68 22-5-1. MyBase的Briefcase功能
屬性 元件 Name AliasName Database Name DataSet TableName DataSource Database Database1 BCDEMOS MyDB - Table Table1 employee.db DataSource1 BDEClientDataSet1 DataSource2 DBGrid DBGrid1 DBGrid2 DBNavigator DBNavigator1 屬性 元件 Name CommandText DBConnection FileName BDEClientDataSet BDEClientDataSet1 select * from employee Database1 employee.xml

69 22-5-1. MyBase的Briefcase功能
加入各事件的程式碼如下,包含表單的OnCreate事件和按鈕的OnClick事件。Main.cpp程式碼 執行程式。

70 22-5-1. MyBase的Briefcase功能
【執行結果】 按下DBNavigator元件上的各按鈕即可對MyBase資料庫內的資料進行檢視與存取的動作;而按下【重新整理】按鈕即可儲存對記錄所做的變更於MyBase的檔案中;按下【更新至資料庫】按鈕更可把變更的結果傳回BDE連結的資料庫。在程式中提供了對MyBase和BDE連結資料庫的檢視功能來方便讀者觀察按下按鈕後不同的執行結果,以了解有無Briefcase功能的差別。

71 22-5-1. MyBase的Briefcase功能
【實例說明】 本程式的資料來源主要分為兩個:MyBase資料檔和BDE連結的資料庫。其中,MyBase資料檔透過物件檢視器中指定的FileName屬性、Open與Close方法來完成存取的動作;至於和BDE資料庫的連結則透過物件檢視器中CommandText屬性與ApplyUpdates方法來完成。值得注意的是FileName屬性必須透過物件檢視器進行指定以避免執行Open方法時從CommandText所指定的內容進行讀取資料集合的動作,也就是必須透過指定FileName屬性的動作來讓CommandText屬性在Open和Close方法呼叫時喪失作用,如此才能達到連結兩個不同資料來源的目的。此外,由於ApplyUpdates方法執行後MyBase資料庫內的變更已經反映至BDE連結的資料庫中,因此必須執行MergeChangeLog和SaveToFile方法以更新MyBase檔案中的內容。在BDEClientDataSet元件中,對資料集合所做的變更皆紀錄於Delta屬性中,並反映到儲存的MyBase檔案。當ApplyUpdate方法被呼叫後Delta屬性的內容會被清空,但MyBase檔案紀錄的Delta內容並不會自動清除,因此需要執行MergeChangeLog和SaveToFile方法以除去MyBase檔案中紀錄的Delta屬性部分。

72 22-5-1. MyBase的Briefcase功能
變更的記錄 含有變更內容的Data Packet檔案

73 MyBase的XML檔案直接儲存 本節透過實例說明介紹如何以自訂的XML檔案作為MyBase資料庫的儲存媒介。這部分程式的實作,除了透過ClientDataSet元件來完成外,還必須藉由XML Mapper輔助程式所產生的XTR轉換檔才能完成。因此,在程式實作前,必須先完成以下三項準備工作: 編寫XML檔案。在這裡我們以myemployee.xml檔案為例。 利用XML Mapper產生XMLData Packet的轉換檔(以ToDp.xtr為例)。詳細的轉換過程請參考22-4-2節所述。 利用和前項步驟相同的方法產生Data PacketXML的轉換檔(以ToXml.xtr為例)。

74 22-5-2. MyBase的XML檔案直接儲存 【操作實例22-6】使用XML檔案直接儲存的MyBase程式
透過XMLTransformProvider元件和XTR轉換檔的使用完成以自訂XML檔案作為儲存媒介的MyBase程式。 產生新專案,並設計表單畫面如下。 屬性 元件 Name TransformRead TransformWrite XMLDataFile Active ProviderName XMLTransformProvider XMLTransformProvider1 TransformationFile=ToDp.xtr TransformationFile=ToXml.xtr myemployee.xml - ClientDataSet ClientDataSet1 True

75 22-5-2. MyBase的XML檔案直接儲存 在按鈕的OnClick事件中加入對應的程式碼如下。
執行程式,即可利用自訂的XML檔案作為MyBase的資料來源。 void __fastcall TForm1::Button1Click(TObject *Sender) { //--"重新整理"按鈕的OnClick事件 ClientDataSet1->Close(); ClientDataSet1->Open(); } // void __fastcall TForm1::Button2Click(TObject *Sender) //--"儲存至檔案"按鈕的OnClick事件 ClientDataSet1->ApplyUpdates(-1);

76 22-5-2. MyBase的XML檔案直接儲存 【執行結果】
當透過DBNavigator元件對資料集合進行變更後,按下【儲存至檔案】按鈕即可儲存這些變更於自訂的 XML檔案中;而按下【重新整理】即可重新讀取XML檔案中的內容。 新增資料後的結果

77 22-5-2. MyBase的XML檔案直接儲存 【實例說明】
在本例中,自定XML文件透過XMLTransformProvider元件和XTR檔案的配合,即可轉換自訂XML文件的內容為符合Data Packet類型的資料集合供ClientDataSet元件進行存取的動作。其中,XMLTransformProvider元件再依寫入和讀取的不同將轉換工作交由不同的XTR轉換檔負責,所以對於僅需寫入或讀取的使用者來說,僅需指定對應的XTR檔案即可,而不需要同時指定兩種XTR轉換檔。

78 本章習題 習題 試簡述XML檔案的優點。 簡述XML、XML Schema和XSL間的關係。 試比較XML Schema和DTD檔案的差異。
自訂XML檔案,並透過Data Binding Wizard的使用,產生對應於自訂XML檔案的Interface。 承上題,試撰寫程式讀取自訂XML檔案內各標籤的內容。 何謂MyBase資料庫? 簡述XML Mapper工具的作用為何?透過該工具可以完成哪些轉換工作? 試使用SQLClientDataSet元件實作Briefcase功能的MyBase程式。


Download ppt "第二十二章 C++ Builder上的XML應用"

Similar presentations


Ads by Google