本文主要是介绍利用MSXML解析xml文件,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
利用MSXML解析xml文件
一般情况我们装载操作xml文件,不会频繁。因此很容易忽略其中的内存泄露问题。但是如果操作不当其中的内存浪费还是令人难以容忍的。
最近做一个文件下栽处理的程序,其中下栽的连接信息是通过解析xml来获得。因此对于xml文件的装载和解析频率非常的高。刚开始采用的方式是初始化库CoInitialize, 利用CoCreateInstance创建IXMLDOMDocument然后装载。可是到实际使用的时候才发现内存消耗的太严重了,就几个任务下去程序占用的内存是以M为单位往上涨个不停。最郁闷的是用CMemoryState来观察,也只是看到了不断的申请内存,并不报泄露。刚开始的时候还怀疑是设计的存储数据的结构本身有问题。仔细查来查去,针对数据结构做了几个小测试程序—— 很不幸的是,还真的有点问题。等把问题解决了 只是稍微好点。
看样子主要问题还不是出在这里。于是做了个测试程序,把每段代码都拿过来做一个循环一千遍的操作,看内存的状态。这一看吓一跳:就一个pDoc->load(_bstr_t(lpszPath)); 就内存消耗疯涨了。想了想大致猜到了问题出那里了,每一次使用IXMLDOMDocument装载之后都要释放(Release)的,看解析的时候原因同样如此。虽然我对整个的这些IXMLDOMNodeList IXMLDOMElement IXMLDOMNode都有释放的,但是在想法上也是针对于他们本身,在最后的时候选择释放的,而实际上是在每次取得这些内容并解析之后如果不在需要的话都是需要释放的。把所有这些地方都改过来,果然就Okay了。
回想起以前在做类似处理的时候由于都是单一性的操作,并且内存也不报泄露。就这么自己把自己给忽悠咯。以前在查资料的时候也没有仔细的注意到,好象强调这个的也不多。
下面给出修订后的xml处理的代码:
#define XML_NODE_TAG "XmlNodeName"
MSXML2::IXMLDOMDocument * pDoc = NULL;
BOOL LoadToc(LPCTSTR lpszPath)
{//装载
HRESULT hr = NULL;
//TRACE("/nLoadXML %s /n",lpszPath);
//TRACE(_T("/nInit MSXML com lib..../n"));
try
{
if (NULL!=pDoc)
{
pDoc->Release();
}
else
{
hr = CoInitialize(NULL);
if(!SUCCEEDED(hr))
return FALSE;
}
// ASSERT(lpszPath!=NULL);
if (lpszPath == NULL) return FALSE;
CoCreateInstance (MSXML::CLSID_DOMDocument,
NULL, CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER,
MSXML::IID_IXMLDOMDocument,
(LPVOID *)&pDoc);
if(!pDoc)
return FALSE;
pDoc->put_async(VARIANT_FALSE);
hr = pDoc->load(_bstr_t(lpszPath));
if(!hr)
{
pDoc = NULL;
return FALSE;
}
Parse(pDoc);
}
catch (...)
{
pDoc = NULL;
}
//TRACE(_T("success/n"));
return TRUE;
}
BOOL Parse(MSXML2::IXMLDOMDocument * pDoc)
{
MSXML2::IXMLDOMNodeList *pList = NULL;
MSXML2::IXMLDOMNode *pNode = NULL;
MSXML2::IXMLDOMElement *pRoot = NULL;
unsigned short buff[NODE_BUFF_MAX_LENGTH];
memset(buff,0,NODE_BUFF_MAX_LENGTH);
pDoc->get_documentElement(&pRoot);
[/img]
ifdef POWER_CHECK
if(pRoot->hasChildNodes() != -1)//-1 is True
{
pRoot->Release();
return FALSE;
}
[img][/img]
f
pRoot->get_childNodes(&pList);
long lCount;
pList->get_length(&lCount);
for(int iCount=0;iCount <lCount;iCount ++)
{
pList->get_item(iCount,&pNode);
if (pNode == NULL) continue;
memset(buff,0,NODE_BUFF_MAX_LENGTH);
GetNodeName(pNode,buff);
if(wcscmp(buff,XML_NODE_TAG)==0)
{
//将数据从xml文件里面解析出来......
pNode->Release();//因为是循环体也可以把这些综合起来放到循环体的开始部分处理
//但是在资源不使用的时候立刻释放是一个比较保险且妥当的办法
continue;
continue;
continue;
}
else
{
//TRACE(_T("UnKnowNode:"));
//wprintf(buff);
//TRACE(_T("/n"));
pNode->Release();
continue;
}
}
pList->Release();
pRoot->Release();
return TRUE;
}
inline BOOL GetNodeName(MSXML2::IXMLDOMNode *pNode, const unsigned short* lpsz )
{
BSTR sNodeType = NULL;
BSTR sNodeName = NULL;
if (NULL==pNode )
return FALSE;
if (NULL==lpsz) return FALSE;
pNode->get_nodeTypeString(&sNodeType);
if(!wcscmp(sNodeType,L"element"))
pNode->get_nodeName(&sNodeName);
else if(!wcscmp(sNodeType,L"text"))
pNode->get_text(&sNodeName);
else
pNode->get_nodeName(&sNodeName);
wcscpy((unsigned short *)lpsz,(const unsigned short *)sNodeName);
SysFreeString(sNodeType);
SysFreeString(sNodeName);
return TRUE;
}
这篇关于利用MSXML解析xml文件的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!