摘 要 本文就树型控件和XML文档之间的数据转移技术进行了探讨,通过递归调用的方法,避免陷入树型控件和XML文档组织数据的复杂逻辑关系中去,简洁了代码,提高了效率。
关键词 树型控件,XML,数据转移
一、引言
树型控件作为一种数据展示和操控控件,具有目录式、分类管理的特征,便于直观、快捷的处理业务数据,得到了广大软件设计人员和软件客户的认可和青睐。但是随着数据存储技术和理论的发展,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中编译调试通过。
|