VS2010 中使用 MSXML生成解析XML文件

初始化com

	if (!AfxOleInit())
	{
		AfxMessageBox("Ole initialize failed.");
		return FALSE;
	}

生成XML文件

void CtestDlg::ConstructDocument()
{
	CComPtr<IXMLDOMDocument>  pXmlDoc;
	CComQIPtr<IXMLDOMProcessingInstruction>	pXmlProInstruction;
	CComQIPtr<IXMLDOMElement>		pXmlRoot;
	CComQIPtr<IXMLDOMComment>		pXmlComment;
	
	CComQIPtr<IXMLDOMElement>		pXmlPage_1;
	CComQIPtr<IXMLDOMElement>		pXmlPage_2;

	CComQIPtr<IXMLDOMElement>		pXmlCtrl_1;
	CComQIPtr<IXMLDOMElement>		pXmlCtrl_2;

	HRESULT hr = pXmlDoc.CoCreateInstance(CLSID_DOMDocument);
	if(!SUCCEEDED(hr)) 
	{         
		MessageBox("创建DOMDocument对象失败");
		return;
	}

	//属性设置
	//pXmlDoc->put_preserveWhiteSpace(VARIANT_TRUE);
	//pXmlDoc->put_async(VARIANT_FALSE);
	//pXmlDoc->put_validateOnParse(VARIANT_FALSE);
	//pXmlDoc->put_resolveExternals(VARIANT_FALSE);

	//添加xml说明
	pXmlDoc->createProcessingInstruction(OLESTR("xml"), OLESTR("version=\"1.0\" encoding=\"utf-8\""), &pXmlProInstruction);
	pXmlDoc->appendChild(pXmlProInstruction, NULL);

	//创建添加根节点
	pXmlDoc->createElement(OLESTR("Root"), &pXmlRoot);
	pXmlDoc->appendChild(pXmlRoot, NULL);
	
	//添加注释
	pXmlDoc->createComment(OLESTR("this is a test"), &pXmlComment);
	pXmlRoot->appendChild(pXmlComment, NULL);

	//创建node1
	pXmlDoc->createElement(OLESTR("test1"), &pXmlCtrl_1);
	//设置节点属性
	pXmlCtrl_1->setAttribute(OLESTR("type"), CComVariant(OLESTR("txt")));
	pXmlCtrl_1->setAttribute(OLESTR("name"), CComVariant(OLESTR("gsy")));
	//设置节点内容
	pXmlCtrl_1->put_text(OLESTR("test1_value"));
	pXmlRoot->appendChild(pXmlCtrl_1, NULL);

	//创建node2
	pXmlDoc->createElement(OLESTR("test2"), &pXmlCtrl_2);
	pXmlCtrl_2->setAttribute(OLESTR("type"), CComVariant(OLESTR("txt")));
	pXmlCtrl_2->setAttribute(OLESTR("name"), CComVariant(OLESTR("ttt")));
	pXmlCtrl_2->put_text(OLESTR("test2_value"));
	pXmlRoot->appendChild(pXmlCtrl_2, NULL);

	//创建属性
	//pXmlDoc->createAttribute(OLESTR("type"), &pXmlAttr_1);
	//pXmlAttr_1->put_value(CComVariant(OLESTR("txt")));
	
	//保存为xml
	pXmlDoc->save(CComVariant(OLESTR("test.xml")));
}
生成的xml文件
<?xml version="1.0" encoding="utf-8"?>
<Root><!--this is a test--><test1 type="txt" name="gsy">test1_value</test1><test2 type="txt" name="ttt">test2_value</test2></Root>

上述生成的代码不易阅读,需要格式化

两种方法。

第一种:添加每个节点后调用如下函数
void CtestDlg::FormatXML(CComPtr<IXMLDOMDocument>& pXmlDoc, CComPtr<IXMLDOMElement>& pXmlNode)
{
	CComPtr<IXMLDOMText>	pXmlText;
	CComPtr<IXMLDOMNode>	pXmlEle;
	BSTR  content = OLESTR("\r\n\t");
	pXmlDoc->createTextNode(content, &pXmlText);
	pXmlNode->appendChild(pXmlText, &pXmlEle);
	pXmlEle.Release();
}
//作用就是添加文本节点回车换行
添加格式化后的代码:
void CtestDlg::ConstructDocument()
{
	CComPtr<IXMLDOMDocument>  pXmlDoc;
	CComQIPtr<IXMLDOMProcessingInstruction>	pXmlProInstruction;
	CComQIPtr<IXMLDOMElement>		pXmlRoot;
	CComQIPtr<IXMLDOMComment>		pXmlComment;

	CComQIPtr<IXMLDOMElement>		pXmlCtrl_1;
	CComQIPtr<IXMLDOMElement>		pXmlCtrl_2;

	HRESULT hr = pXmlDoc.CoCreateInstance(CLSID_DOMDocument);
	if(!SUCCEEDED(hr)) 
	{         
		MessageBox("创建DOMDocument对象失败");
		return;
	}

	//属性设置
	//pXmlDoc->put_preserveWhiteSpace(VARIANT_TRUE);
	//pXmlDoc->put_async(VARIANT_FALSE);
	//pXmlDoc->put_validateOnParse(VARIANT_FALSE);
	//pXmlDoc->put_resolveExternals(VARIANT_FALSE);

	//添加xml说明
	pXmlDoc->createProcessingInstruction(OLESTR("xml"), OLESTR("version=\"1.0\" encoding=\"utf-8\""), &pXmlProInstruction);
	pXmlDoc->appendChild(pXmlProInstruction, NULL);

	//创建添加根节点
	pXmlDoc->createElement(OLESTR("Root"), &pXmlRoot);
	pXmlDoc->appendChild(pXmlRoot, NULL);
	FormatXML(pXmlDoc,pXmlRoot);		//第二参数为当前节点

	//添加注释
	pXmlDoc->createComment(OLESTR("this is a test"), &pXmlComment);
	pXmlRoot->appendChild(pXmlComment, NULL);
	FormatXML(pXmlDoc,pXmlRoot);

	//创建node1
	pXmlDoc->createElement(OLESTR("test1"), &pXmlCtrl_1);
	//设置节点属性
	pXmlCtrl_1->setAttribute(OLESTR("type"), CComVariant(OLESTR("txt")));
	pXmlCtrl_1->setAttribute(OLESTR("name"), CComVariant(OLESTR("gsy")));
	//设置节点内容
	pXmlCtrl_1->put_text(OLESTR("test1_value"));
	pXmlRoot->appendChild(pXmlCtrl_1, NULL);
	FormatXML(pXmlDoc,pXmlRoot);

	//创建node2
	pXmlDoc->createElement(OLESTR("test2"), &pXmlCtrl_2);
	pXmlCtrl_2->setAttribute(OLESTR("type"), CComVariant(OLESTR("txt")));
	pXmlCtrl_2->setAttribute(OLESTR("name"), CComVariant(OLESTR("ttt")));
	pXmlCtrl_2->put_text(OLESTR("test2_value"));
	pXmlRoot->appendChild(pXmlCtrl_2, NULL);
	FormatXML(pXmlDoc,pXmlRoot);

	//创建属性
	//pXmlDoc->createAttribute(OLESTR("type"), &pXmlAttr_1);
	//pXmlAttr_1->put_value(CComVariant(OLESTR("txt")));
	
	//保存为xml
	pXmlDoc->save(CComVariant(OLESTR("test.xml")));
}
结果:
<?xml version="1.0" encoding="utf-8"?>
<Root>
	<!--this is a test-->
	<test1 type="txt" name="gsy">test1_value</test1>
	<test2 type="txt" name="ttt">test2_value</test2>
	</Root>

第二种方法:使用sheet.xsl文件格式化,这个文件可以自定义显示格式

/**
 *Description:
 *  格式化XML文件
 *Author: 
 *	GAO-SHI-YONG 
 *Paramter:
 *  [in] pXmlDoc:document对象
 *  [in] savePath : 保存路径
 *  [out] result: 0:成功;-1:参数1为空;-2:路径为空;-3 -- -7:XML文件创建失败
 *Return:
 *  
**/
void CtestDlg::FormatXML(CComPtr<IXMLDOMDocument>& pXmlDoc, CString& savePath, int& result)
{
	if (pXmlDoc == NULL)
	{
		result = -1;
		return;
	}
	if (savePath.IsEmpty())
	{
		result = -2;
		return;
	}

	//创建document对象
	CComPtr<IXMLDOMDocument>	LoadXML;
	HRESULT hr1 = LoadXML.CoCreateInstance(CLSID_DOMDocument);
	if(!SUCCEEDED(hr1)) 
	{         
		result = -3;
		return;
	}

	//加载xsl模板
	VARIANT_BOOL  vb;
	CString	formatFilePath = m_root_dir + "StyleSheet.xsl";
	BSTR		bstr = formatFilePath.AllocSysString();
	hr1 = LoadXML->load(CComVariant(bstr), &vb);
	SysFreeString(bstr);

	if (!SUCCEEDED(hr1))
	{
		result = -4;
		return ;
	}

	//创建格式化document对象
	CComPtr<IXMLDOMDocument>	pXMLformatDoc;
	hr1 = pXMLformatDoc.CoCreateInstance(CLSID_DOMDocument);
	if (FAILED(hr1))
	{
		result = -5;
		return ;
	}

	CComQIPtr<IDispatch>	pDispatch;
	hr1 = pXMLformatDoc->QueryInterface(IID_IDispatch, (void**)&pDispatch);
	if (FAILED(hr1))
	{
		result = -6;
		return ;
	}

	_variant_t  vtOutObject;
	vtOutObject.vt = VT_DISPATCH;
	vtOutObject.pdispVal = pDispatch;
	vtOutObject.pdispVal->AddRef();

	//将一个document对象按照xsl模板转化为另一个document对象
	hr1 = pXmlDoc->transformNodeToObject(LoadXML, vtOutObject);
	if (FAILED(hr1))
	{
		result = -7;
		return ;
	}

	//修改xml encoding 属性
	CComQIPtr<IXMLDOMNode>	pXmlRoot;
	CComQIPtr<IXMLDOMNamedNodeMap>  pXmlNodeMap;
	CComQIPtr<IXMLDOMNode>	pXmlNode;
	pXMLformatDoc->get_firstChild(&pXmlRoot);
	pXmlRoot->get_attributes(&pXmlNodeMap);
	pXmlNodeMap->getNamedItem(OLESTR("encoding"), &pXmlNode);
	pXmlNode->put_nodeValue(CComVariant(OLESTR("utf-8")));

	//保存格式化之后的document对象
	BSTR  bstr2 = savePath.AllocSysString();
	pXMLformatDoc->save(CComVariant(bstr2));
	SysFreeString(bstr2);

	result = 0;
}
StyleSheet.xsl文件下载地址:下载地址

使用这个函数不必和第一种方法一样,而是直接在生成xmldocment之后传入该函数即可
举例:

	//格式化xml文件
	int result = 0;
	FormatXML(pXmlDoc, xmlPath, result);
	if (result != 0)
	{
		MESSAGE_BOX("Create XML file failed. More details view log.txt file.");
		return;
	}

解析XML文件

代码:

BOOL CtestDlg::GetInfoFromXml(CString& xmlFile, vector<pPageInfo>& vcPages)
{
	//读取XML
	CComPtr<IXMLDOMDocument> spDoc; //DOM	
	spDoc.CoCreateInstance(CLSID_DOMDocument);
	VARIANT_BOOL vb;
	BSTR		filename = xmlFile.AllocSysString();
	spDoc->load(CComVariant(filename), &vb); //加载XML文件
	SysFreeString(filename);
	
	/*
	//获取xml默认文件属性 version,encoding,standalone
	CComQIPtr<IXMLDOMNode>	pXmlRoot;
	CComQIPtr<IXMLDOMNamedNodeMap>  pXmlNodeMap;
	CComQIPtr<IXMLDOMNode>	pXmlNode;
	spDoc->get_firstChild(&pXmlRoot);
	BSTR		test1111;
	pXmlRoot->get_xml(&test1111);	//获取Root节点xml内容
	pXmlRoot->get_attributes(&pXmlNodeMap);		//获取Root节点属性列表
	pXmlNodeMap->getNamedItem(OLESTR("encoding"), &pXmlNode);	//这里注意node属性也是一个节点
	BSTR		test222;
	pXmlNode->get_xml(&test222);
	pXmlNode->get_text(&test222);		//获取节点值
	*/
	
	///根节点
	CComPtr<IXMLDOMElement> spRootEle;
	spDoc->get_documentElement(&spRootEle); 

	///获取Root节点属性,即屏幕高和宽
	VARIANT	attrWidth, attrHeight;
	spRootEle->getAttribute(OLESTR("Width"), &attrWidth);
	spRootEle->getAttribute(OLESTR("Height"), &attrHeight);
	CString	strWidth(attrWidth.bstrVal);
	CString strHeight(attrHeight.bstrVal);

	///子节点列表
	CComPtr<IXMLDOMNodeList> spNodeList;
	spRootEle->get_childNodes(&spNodeList); 
	///子节点数
	long nLen;
	spNodeList->get_length(&nLen);
	///遍历子节点
	for (long i = 0; i != nLen; ++i)
	{
		CComPtr<IXMLDOMNode> spNode;
		spNodeList->get_item(i, &spNode);
		///节点处理函数
		ProcessNode(spNode);
	}
	return TRUE;
}


//节点处理函数
void ProcessNode(CComPtr<IXMLDOMNode>& spNode)
{
	CComBSTR bsNodeName;
	spNode->get_nodeName(&bsNodeName); //节点名
	AfxMessageBox(COLE2CT(bsNodeName));
	CComVariant varVal;
	spNode->get_nodeValue(&varVal); //节点值
	AfxMessageBox(COLE2CT(varVal.bstrVal));

	DOMNodeType eNodeType;
	spNode->get_nodeType(&eNodeType);
	if (eNodeType == NODE_ELEMENT) //只有NODE_ELEMENT类型才能包含有属性和子节点
	{
		//递归遍历节点属性
		CComPtr<IXMLDOMNamedNodeMap> spNameNodeMap;
		spNode->get_attributes(&spNameNodeMap);
		long nLength;
		spNameNodeMap->get_length(&nLength);
		for (long i = 0; i != nLength; ++i)
		{
			CComPtr<IXMLDOMNode> spNodeAttrib; //注意属性也是一个IXMLDOMNode
			spNameNodeMap->get_item(i, &spNodeAttrib);
			ProcessNode(spNodeAttrib);
		}

		//递归遍历子节点
		CComPtr<IXMLDOMNodeList> spNodeList;
		spNode->get_childNodes(&spNodeList);
		spNodeList->get_length(&nLength);
		for (long i = 0; i != nLength; ++i)
		{
			CComPtr<IXMLDOMNode> spChildNode;
			spNodeList->get_item(i, &spChildNode);
			ProcessNode(spChildNode);
		}
	}
}

xml文件为上面生成的

说明:

对于解析xml文件来说,不同场景的解析过程中处理不一样,但是总的来说,就是遍历节点读取属性及对应的属性值,或者读取节点值。




本文参考网址: //使用了智能指针 https://www.cnblogs.com/lingyun1120/archive/2011/11/02/2232709.html //element与node区别 https://www.iteye.com/blog/cscq-1716676 //csdn类似使用MSXML https://blog.csdn.net/xuqiang918/article/details/36435557 //老外写的 https://www.codeproject.com/Articles/43309/How-to-create-a-simple-XML-file-using-MSXML-in-C //写的还行,注释很多 https://www.cnblogs.com/xulei/archive/2007/12/11/975983.html
相关推荐
©️2020 CSDN 皮肤主题: 技术黑板 设计师:CSDN官方博客 返回首页