XML文件读写

XML文件读写

这里是利用COM组建对xml文件进行操作,所以程序进入时要进行COM组件的初始化和卸载

::CoInitialize(NULL); 和 ::CoUninitialize();要对应

为了不影响其他地方的操作,最好把这个放在项目的开始和结束

你也可以使用AfxOleInit();他对CoInitialize进行了封装,具体的区别可以到网上查一下

另外确保安装了MS XML Parser 运行库

 

 

使用时需要加上

#import <msxml3.dll>
 

下面的两个函数就是对xml文件的操作,大部分操作都已涉及

 

///////////////////////////////////////////////////////////////////////////////
#import <msxml3.dll>
typedef MSXML2::IXMLDOMDocumentPtr DOMDocumentPtr;
typedef MSXML2::IXMLDOMElementPtr DOMElementPtr;
typedef MSXML2::IXMLDOMProcessingInstructionPtr	DOMProInstructionPtr;
typedef MSXML2::IXMLDOMNamedNodeMapPtr DOMNamedNodeMapPtr;
typedef MSXML2::IXMLDOMNodeListPtr DOMNodeListPtr;
typedef MSXML2::IXMLDOMNodePtr DOMNodePtr;
typedef MSXML2::IXMLDOMTextPtr DOMTextPtr;
///////////////////////////////////////////////////////////////////////////////
int ReadXML(CString szXMLFile)
{
	if (szXMLFile.IsEmpty())
		return -1;

	DOMDocumentPtr pXMLDoc;
	CString szText;

	// 初始化COM组件,必须与::CoUninitialize();相对应
	// 这里可以这么使用,但以后尽量在程序开始调用,程序结束卸载,否则可能会影响到其他地方使用
	// 用AfxOleInit();也可以,但也必须确保只调用了一次,最好放在程序的开始
	::CoInitialize(NULL);
	
	// 创建DOMDocument对象,并判断是否创建成功
	HRESULT	hr = pXMLDoc.CreateInstance(__uuidof(MSXML2::DOMDocument30));
	if(!SUCCEEDED(hr))
	{
		MessageBox(NULL, "无法创建DOMDocument对象,请检查是否安装了MS XML Parser 运行库!", "Error", MB_ICONERROR|MB_OK);
		return -1;
	}

	if(pXMLDoc->load(_variant_t(szXMLFile)) == FALSE)
	{
		MessageBox(NULL, "无法打开存档!", "Error", MB_ICONERROR|MB_OK);
		return -2;
	}

	// 是否有根节点,取得根节点
	DOMElementPtr pRootElem = pXMLDoc->GetdocumentElement();
	if (pRootElem == NULL)
		return -3;

	// 取得根节点的名字
	szText = (char*)(pRootElem->GetnodeName());

	// 在根节点下查找名叫Globals的节点并取得
	DOMNodePtr pGlobalNode = pRootElem->selectSingleNode("Globals");
	if (pGlobalNode == NULL)
		return -3;
	
	// 取得属性列表
	DOMNamedNodeMapPtr pNodeMap = pGlobalNode->Getattributes();

	// 根据名字直接取得属性节点并获取值
	DOMNodePtr pAttribNode = pNodeMap->getNamedItem("Attrib");
	szText = (char *)(pAttribNode->Gettext());
	pAttribNode = pNodeMap->getNamedItem("作用");
	szText = (char *)(pAttribNode->Gettext());

	// 另外在有些情况下Node可以转换成Element使用
	DOMElementPtr pGlobalElem = pGlobalNode;
	szText = (char*)(_bstr_t)(pGlobalElem->getAttribute("Attrib"));
	szText = (char*)(_bstr_t)(pGlobalElem->getAttribute("作用"));
	
	// 如果不知道名字可以取得属性的个数,逐个查找属性
	long len = pNodeMap->Getlength();
	for (int i=0; i<len; ++i)
	{
		pAttribNode = pNodeMap->Getitem(i);
		szText = (char *)(pAttribNode->GetnodeName());	// 取得属性名字
		szText = (char *)(pAttribNode->Gettext());		// 取得属性值
	}
	
	DOMNodePtr pTempNode;
	// 取得Globals下的子节点
	if((pTempNode = pGlobalNode->GetfirstChild()))
	{
		szText = (char*)pTempNode->GetnodeName();
		szText = (char*)pTempNode->Gettext();

		// 循环取得相邻的节点
		while((pTempNode = pTempNode->GetnextSibling()))
		{
			szText = (char*)pTempNode->GetnodeName();
			szText = (char*)pTempNode->Gettext();
		}
	}

	// 从根节点中查找Data的子节点
	DOMNodePtr pDataNode = pRootElem->selectSingleNode("Data");
	if (pDataNode == NULL)
		return -1;

	// 从Data节点下列取出所有叫Data的节点
	DOMNodeListPtr pDataList = pDataNode->selectNodes("Data");
	len = pDataList->Getlength();
	for(i=0; i<len; ++i)
	{
		pTempNode = pDataList->Getitem(i);
		szText = (char*)pTempNode->GetnodeName();
		szText = (char*)pTempNode->Gettext();
	}

	// 确保卸载掉所有的对象才能调用CoUninitialize
	if(pNodeMap)pNodeMap.Detach();
	if(pAttribNode)pAttribNode.Detach();
	if(pTempNode)pTempNode.Detach();
	if(pGlobalNode)pGlobalNode.Detach();
	if(pGlobalElem)pGlobalElem.Detach();
	if(pDataNode)pDataNode.Detach();
	if(pDataList)pDataList.Detach();
	if(pRootElem)pRootElem.Detach();
	if(pXMLDoc)pXMLDoc.Detach();

	// 卸掉COM,必须与CoInitialize对应
	::CoUninitialize();
	return 0;
}

int SaveXML(CString szXMLFile)
{
	DOMDocumentPtr pXMLDoc;
	CString szText;

	// 初始化COM组件,必须与::CoUninitialize();相对应
	// 这里可以这么使用,但以后尽量在程序开始调用,程序结束卸载,否则可能会影响到其他地方使用
	// 用AfxOleInit();也可以,但也必须确保只调用了一次,最好放在程序的开始
	::CoInitialize(NULL);

	// 创建DOMDocument对象,并判断是否创建成功
	HRESULT	hr = pXMLDoc.CreateInstance(__uuidof(MSXML2::DOMDocument30));
	if(!SUCCEEDED(hr))
	{
		MessageBox(NULL, "无法创建DOMDocument对象,请检查是否安装了MS XML Parser 运行库!", "Error", MB_ICONERROR|MB_OK);
		return -1;
	}

	// 创建头节点
	DOMProInstructionPtr pXmlProNode = pXMLDoc->createProcessingInstruction(_bstr_t("xml"),_bstr_t("version=\"1.0\" encoding = \"GB2312\""));
	pXMLDoc->appendChild((MSXML2::IXMLDOMNodePtr)pXmlProNode);	
	pXmlProNode.Detach();	//以后不再用的,卸掉

	// 创建并添加根节点
	// 创建一个节点
	DOMElementPtr pXmlRoot = pXMLDoc->createElement("root");
	// 添加到文档中
	pXMLDoc->appendChild(pXmlRoot);

	// 创建一个节点
	DOMElementPtr pGlobalNode = pXMLDoc->createElement("Globals");
	// 添加到根节点中
	pXmlRoot->appendChild(pGlobalNode);

	// 添加两个属性
	pGlobalNode->setAttribute("Attrib", "Value");
	pGlobalNode->setAttribute("作用", "记录全局数据");

	DOMElementPtr pTempNode = pXMLDoc->createElement("Author");
	pTempNode->Puttext("Ren.Xia");// 添加内容
	pGlobalNode->appendChild(pTempNode);
	pTempNode.Detach();

	pTempNode = pXMLDoc->createElement("Date");
	pTempNode->Puttext("2011-02-12");// 添加内容
	pGlobalNode->appendChild(pTempNode);
	pTempNode.Detach();
	pGlobalNode.Detach();

	// 在Root下创建Data子节点
	DOMElementPtr pDataNode = pXMLDoc->createElement("Data");
	pDataNode->setAttribute("Attrib", "Value");
	pDataNode->setAttribute("作用", "记录数据");
	pXmlRoot->appendChild(pDataNode);

	for (int i=0; i<100; ++i)
	{
		pTempNode = pXMLDoc->createElement("Data");
		szText.Format("%d", i);
		pTempNode->Puttext((_bstr_t)szText);
		pDataNode->appendChild(pTempNode);
		pTempNode.Detach();
	}
	pDataNode.Detach();

	// 判断名字是否为空
	if (szXMLFile.IsEmpty())
	{
		pXmlRoot.Detach();
		pXMLDoc.Detach();
		return -2;
	}

	// 存储并判断是否成功
	hr = pXMLDoc->save((LPCTSTR)szXMLFile);
	pXmlRoot.Detach();
	pXMLDoc.Detach();
	if(!SUCCEEDED(hr))
	{
		MessageBox(NULL, "无法保存!", "Error", MB_ICONERROR|MB_OK);
		return -3;
	}	
	MessageBox(NULL, "保存完毕!", "Error", MB_ICONASTERISK|MB_OK);
	
	// 卸掉COM,必须与CoInitialize对应
	::CoUninitialize();
	return 0;
}


 

另外如果知道一个节点的名字"Data",但是不知道在哪一层,那个树下

可以在查找时名字前加个"//"这样就表示在任意一层查找  

 

pRootElem->selectSingleNode(" //Data");
 

 



    本文附件下载:
  • XML.rar (484.4 KB)

你可能感兴趣的:(XML文件读写)