Posted on 2009-08-25 15:29
天之驕子 閱讀(5126)
評(píng)論(0) 編輯 收藏 引用
好久沒(méi)有在VC++里面解析XML了,昨天遇到一個(gè)問(wèn)題,從昨天下午一直到今天上午,差不多搞了一天,才終于把問(wèn)題解決了。
使用MSXML在VC++中解析XML文件時(shí)候,只需要做到下面幾點(diǎn):
1、初始化COM庫(kù),CoInitialize(NULL);可以放在InitInstance()函數(shù)里面。釋放COM庫(kù),CoUninitialize();可以放在ExitInstance()函數(shù)里面。
2、在頭文件里面加入如下代碼
#import "MSXML6.dll" rename_namespace("MSXML6") named_guids
using namespace MSXML6;
因?yàn)榻馕龅臅r(shí)候要用到CComVariant類,所以還要加上
#include <atlbase.h>
3、解析XML文件。
需要解析的XML文件如下:
<?xml version="1.0" encoding="UTF-8"?>
<SCL xmlns="http://www.iec.ch/61850/2003/SCL">
<Address type="MAC-Address" xsi:type="tP_MAC-Address">
01-0C-CD-01-00-08
</Address>
</SCL>
首先要加載XML文件,代碼如下:
HRESULT hr;
IXMLDOMDocument *pDoc=NULL;

CString strFileName;
CFileDialog fileDlg(TRUE);
fileDlg.m_ofn.lpstrTitle="打開(kāi)XML文件";
fileDlg.m_ofn.lpstrFilter="XML Files(*.xml)\0*.xml\0All Files(*.*)\0*.*\0\0";
fileDlg.m_ofn.lpstrDefExt="xml";
if(fileDlg.DoModal() != IDOK)
return;
strFileName=fileDlg.GetPathName(); //獲得要解析的XML文件的路徑名
ASSERT(!strFileName.IsEmpty());

if(SUCCEEDED(CoCreateInstance(CLSID_DOMDocument,NULL,
CLSCTX_INPROC_SERVER,IID_IXMLDOMDocument,(void**)&pDoc))) //創(chuàng)建Document對(duì)象

{
CComVariant vPath(strFileName);
VARIANT_BOOL isSuccessful;
pDoc->raw_load(vPath,&isSuccessful); //加載要解析的XML文件
if(isSuccessful!=VARIANT_TRUE)

{
AfxMessageBox("wrong!");
return;
}
}
我當(dāng)時(shí)在加載XML文件的時(shí)候老是報(bào)錯(cuò),本來(lái)以為是代碼的問(wèn)題,找了半天都沒(méi)問(wèn)題呀。后來(lái)發(fā)現(xiàn)XML文件的問(wèn)題,問(wèn)題出在xsi:type上,如果將xsi:type改成別的(比如ype就可以了);或者是在根元素里面定義好xsi的意義,修改后的XML文件如下
<?xml version="1.0" encoding="UTF-8"?>
<SCL xmlns="http://www.iec.ch/61850/2003/SCL" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Address type="MAC-Address" xsi:type="tP_MAC-Address">
01-0C-CD-01-00-08
</Address>
</SCL>
現(xiàn)在加載XML文件已經(jīng)沒(méi)有問(wèn)題了,下面就是解析XML文件了。我所做的工作是得到元素Address的兩個(gè)屬性的名稱type和xsi:type,以及它們的屬性值。
我原來(lái)的解析代碼是:
IXMLDOMElement *pRootElement=NULL;
IXMLDOMNode *pRootNode=NULL;

IXMLDOMNamedNodeMap *pAttrMap=NULL;
IXMLDOMNode *pAttrNode=NULL;
IXMLDOMNode *pAddrNode=NULL;

CString strName,strText;
BSTR bsName,bsText;

hr=pDoc->get_documentElement(&pRootElement);
if(SUCCEEDED(hr) && (pRootElement!=NULL))

{
hr=pRootElement->QueryInterface(IID_IXMLDOMNode,(void**)&pRootNode);
if(SUCCEEDED(hr))

{

hr=pRootNode->get_firstChild(&pAddrNode);
if(SUCCEEDED(hr) && (pAddrNode!=NULL))

{
pAddrNode->get_attributes(&pAttrMap);
long length=0;
pAttrMap->get_length(&length);
for(int i=0;i<length;i++)

{
hr=pAttrMap->get_item(i,&pAttrNode);
if(SUCCEEDED(hr) && (pAttrNode!=NULL))

{
pAttrNode->get_baseName(&bsName);
pAttrNode->get_text(&bsText);
strName=bsName;
strText=bsText;
SysFreeString(bsName);
SysFreeString(bsText);
}
}
}
}
}
后來(lái)調(diào)試的時(shí)候發(fā)現(xiàn),對(duì)xsi:type屬性節(jié)點(diǎn)調(diào)用get_basename()方法,得到的是type,而不是xsi:type;當(dāng)然對(duì)type屬性節(jié)點(diǎn)調(diào)用get_basename()方法,得到的是type,這個(gè)正常。后來(lái)我改用IXMLDOMNode的get_nodeName()方法,才把問(wèn)題解決了。對(duì)xsi:type屬性節(jié)點(diǎn)調(diào)用get_nodename()方法,得到的是xsi:type;對(duì)type屬性節(jié)點(diǎn)調(diào)用get_nodename()方法,得到的是type。
修改后的VC++代碼如下
IXMLDOMElement *pRootElement=NULL;
IXMLDOMNode *pRootNode=NULL;

IXMLDOMNamedNodeMap *pAttrMap=NULL;
IXMLDOMNode *pAttrNode=NULL;
IXMLDOMNode *pAddrNode=NULL;

CString strName,strText;
BSTR bsName,bsText;

hr=pDoc->get_documentElement(&pRootElement);
if(SUCCEEDED(hr) && (pRootElement!=NULL))

{
hr=pRootElement->QueryInterface(IID_IXMLDOMNode,(void**)&pRootNode);
if(SUCCEEDED(hr))

{

hr=pRootNode->get_firstChild(&pAddrNode);
if(SUCCEEDED(hr) && (pAddrNode!=NULL))

{
pAddrNode->get_attributes(&pAttrMap);
long length=0;
pAttrMap->get_length(&length);
for(int i=0;i<length;i++)

{
hr=pAttrMap->get_item(i,&pAttrNode);
if(SUCCEEDED(hr) && (pAttrNode!=NULL))

{
pAttrNode->get_nodeName(&bsName);
pAttrNode->get_text(&bsText);
strName=bsName;
strText=bsText;
SysFreeString(bsName);
SysFreeString(bsText);
}
}
}
}
}