一、引言
樹型控件作為一種數據展示和操控控件,具有目錄式、分類管理的特征,便於直觀、快捷的處理業務數據,得到了廣大軟件設計人員和軟件客戶的認可和青睐。但是隨著數據存儲技術和理論的發展,XML 技術作為一種成熟的數據存儲和管理技術,也日益得到人們的廣泛關注。由於它們各自所具有的優點,以及它們在數據的展示形式上的相似性,樹型控件和XML技術在軟件設計中一起應用的案例越來越多。本文就程序設計中樹型控件和XML文件之間的數據轉移問題進行探討,並設計了相應的數據轉移程序。
二、XML特點
隨著XML技術的不斷發展和完善,XML逐漸成為數據存儲和交換的標准格式,廣泛應用於包括小型的配置文件到公司級數據倉庫等數據管理和服務行業。XML文檔的半結構化數據組合特征,方便了人們管理數據的需要。它在數據的表示和存儲方面具有許多優勢,主要表現在:
1.天然的樹形結構。由於XML以樹型結構組織數據,符合了人們認識和組織事物的習慣,因此選用XML形式描述不同事物之間的邏輯關系,是一種自然的選擇。這樣,基於XML標准豐富的功能,能夠有效地降低成本,提高效率。
2.良好的自描述性。基於XML的半結構化數據具有強大的自描述能力,能夠大大增強數據的獨立性,便於不同事物之間獨立地存儲數據,同時又能保證不同節點之間的邏輯關系。
三、編程設計
1. 接口初始化
由於對XML文件的操作,應用了OLE技術,因此,在系統創建時,應首先調用AfxOleInit()函數初始化OLE動態鏈接庫。具體代碼如下:
if (!AfxOleInit())
AfxMessageBox("OLE initialization Error!");
2. 讀寫XML文件
XML 作為一種獨立的技術框架,以及數據的半結構化存儲方式,都決定了對XML文件中數據的訪問和操作具有一定的特殊性,需要通過專門的接口才能訪問。在編程中,首先應定一個訪問XML文件的文檔對象,然後創建該對象,並調入目標XML文件來存取和組織數據。具體實現代如下:
CXMLDOMDocument2 Doc; //定義XML文檔對象
try
{
Doc = CDOMDocument40Class::CreateXMLDOMDocument2(); //創建XML文檔對象
}
catch (CComException *pE)
{
pE->Delete();
return;
}
Doc.SetAsync(FALSE);
if (Doc.Load((LPCSTR) strFileName)) //加載XML文件
{
entityNode = Doc.SelectSingleNode("學科門類"); //訪問XML文件的第一個節點
strNodeName=entityNode.GetNodeName(); //獲得XML文檔中的節點名稱
hItem = m_Tree.InsertItem(strNodeName,TVI_ROOT); //將XML節點名稱增加到樹型結構的根節點的位置 }
else
{
CString str("文件不存在或者文檔內容為空!");
MessageBox(str,NULL,MB_OK);
return;
}
3. 將XML文件的半結構化數據轉移到樹型控件
樹型控件和XML文件的數據轉移,需要將XML文件的半結構化數據轉移到樹型控件,以及將樹型控件中的數據轉移到XML文件。
將XML 文件的半結構化數據轉移到樹型控件時,應首先訪問XML文件的根節點,獲得根節點的名稱,並增加的相應的樹型控件的根節點的位置,然後調用遞歸函數 BulitTreeFromXMLFiles(HTREEITEM hItem,CXMLDOMNode entityNode)實現數據的轉移,下面詳細介紹該遞歸函數的設計流程及編碼實現。
//根據XML文件的內容生成樹型控件
Void BulitTreeFromXMLFiles(HTREEITEM hItem,CXMLDOMNode entityNode)
{
HTREEITEM hSubItem; //樹型子節點
CString strNodeName=""; //子節點名稱
BOOL BeWorking; //是否擁有子節點標志
int count; //子節點的個數
CXMLDOMNodeList nodeLists; //子節點列表
BeWorking=entityNode.HasChildNodes(); //節點entityNode是否擁有子節點
if (BeWorking)
{
//有子節點時,獲得所有的子節點並記錄子節點的個數
nodeLists=entityNode.GetChildNodes();
count=nodeLists.GetLength();
}
int i=0; //計數器
//遍歷節點entityNode擁有的所有子節點,並增加到樹型控件中
while (BeWorking &&(i<count) ) //當前節點有子節點時,並且i<count
{
//獲得第i個子節點,並將節點名稱增加到樹型控件的相應位置
entityNode=nodeLists.GetItem(i);
strNodeName=entityNode.GetNodeName();
hSubItem= m_Tree.InsertItem(strNodeName,hItem);
//判斷第i個子節點是否擁有子節點,進入遞歸調用
BulitTreeFromXMLFiles(hSubItem, entityNode);
i++;
}
}
4. 將樹型控件中的數據轉移到XML文件
將樹型控件中的數據轉移到XML 文件時,只需要將樹型結構的內容依次增加到相應的XML文檔對象DOC中,直到數據轉移完畢,將該文檔對象保存成XML文件即可。其主要過程可通過遞歸函數BulitXMLFilesFromTree( HTREEITEM hItem, CXMLDOMElement entityNode,CXMLDOMDocument2 Doc1 )來實現。
Void BulitXMLFilesFromTree( HTREEITEM hItem, CXMLDOMElement entityNode,
CXMLDOMDocument2 Doc1 )
{
HTREEITEM hSubItem;
CString strNodeName=""; //子節點名稱
BOOL BeWorking; //是否擁有子節點標志
int count = 0; //子節點的個數
CObArray nodeLists;
nodeLists.SetSize(100,-1); //設置對象數組
BeWorking=m_Tree.ItemHasChildren( hItem ); //樹型控件中的當前節點是否擁有子節點
//當前節點是否擁有子節點時,記錄所有的子節點,並計算子節點的數量
if (BeWorking)
{
hSubItem = m_Tree.GetChildItem( hItem );
count++;
nodeLists.SetAt( count-1, (CObject*)hSubItem);
hSubItem = m_Tree.GetNextSiblingItem(hSubItem);
while ( hSubItem !=NULL)
{
count++;
nodeLists.SetAt( count-1, (CObject*)hSubItem);
hSubItem = m_Tree.GetNextSiblingItem(hSubItem);
}
}
int i=0; //計數器
//遍歷hItem的所有子節點,並增加到DOC對象中
while (BeWorking && (i<count) ) //當前節點有子節點時
{
//獲得第i個子節點
hSubItem = (HTREEITEM)nodeLists.GetAt(i);
strNodeName = m_Tree.GetItemText(hSubItem);
CXMLDOMElement newNode;
newNode = Doc1.CreateElement(strNodeName);
entityNode.AppendChild( newNode ); //增加到DOC對象的相應位置
//判斷第i個子節點是否擁有子節點,進入遞歸調用
BulitXMLFilesFromTree(hSubItem, newNode, Doc1);
i++;
}
nodeLists.RemoveAll();
程序運行界面
}
四、結語
通過遞歸函數實現XML文檔數據和樹型控件數據之間的轉移,不僅代碼簡潔,便於理解,而且能夠較大的提高程序的運行效率。本軟件代碼在WinXP操作系統上,安裝MSXML4.0開發包, VC++6.0中編譯調試通過。