关于MSXML的使用

xharry 2005-12-20 01:30:48
问题1:如何取得xml的第一行,即
<?xml version="1.0" encoding="gb2312" ?>
比如我想取version,该怎么取?(请不要用文件读取的方式,我想知道MSXML是不是本身就支持,
因为它用createProcessingInstruction来写,为什么没有取:()


问题2:使用MSXML要注意哪些资源要释放??
以下是我的代码,为什么 RELEASE(pDoc)加上了,Debug的时候可以看到有例外.
而RELEASE(pSubNode)加上了,就直接出错了。这两行注释掉,就什么问题没有。
请问这些资源要释放么??

#define RELEASE(pInterface) \
{\
pInterface->Release();\
pInterface = NULL;\
}\

void xml()
{
// 读取xml代码需要放在try块,因为建立com可能会产生exception
try{
CoInitialize(NULL); // 初始化com组件,
MSXML::IXMLDOMDocumentPtr pDoc;

// 创建一个com进程
HRESULT hr = pDoc.CreateInstance(__uuidof(MSXML::DOMDocument));
if(!SUCCEEDED(hr))
{
AfxMessageBox("failure");
}

pDoc->load("rss.xml");


MSXML::IXMLDOMNodeListPtr pNodeList = NULL;
pNodeList = pDoc->selectNodes("rss/channel/item");
MSXML::IXMLDOMNodePtr pSubNode;

CString strTemp;
for(int i=0; i<pNodeList->Getlength(); i++)
{
pSubNode=pNodeList->nextNode()->selectSingleNode("title");
_bstr_t strRequestType=pSubNode->Gettext();
strTemp=strRequestType.operator char *();
AfxMessageBox(strTemp);
}

//RELEASE(pSubNode);
//RELEASE(pDoc);
}catch(...)
{
AfxMessageBox(_T("Exception occurred"));
}

CoUninitialize();

}
...全文
423 8 打赏 收藏 转发到动态 举报
写回复
用AI写文章
8 条回复
切换为时间正序
请发表友善的回复…
发表回复
xharry 2005-12-22
  • 打赏
  • 举报
回复
懂了,非常感谢
AvalonFX 2005-12-22
  • 打赏
  • 举报
回复
过会儿就好了
CSDN的服务器的刷新机制有问题
xharry 2005-12-22
  • 打赏
  • 举报
回复
帖子我已经结了,怎么看起来还没结?????
xharry 2005-12-21
  • 打赏
  • 举报
回复
就是说,我在循环中每次都得释放了?

for(int i=0; i<pNodeList->Getlength(); i++)
{
pSubNode=pNodeList->nextNode()->selectSingleNode("title");
_bstr_t strRequestType=pSubNode->Gettext();
strTemp=strRequestType.operator char *();
AfxMessageBox(strTemp);
pSubNode->Release();
}
AvalonFX 2005-12-21
  • 打赏
  • 举报
回复
顶之
coolzdp 2005-12-21
  • 打赏
  • 举报
回复
version Property
Specifies the version to include in XML declarations. For example: <?xml version="1.0">.

Syntax
[propput]
HRESULT version (
[in] BSTR strVersion);
[propget]
HRESULT version (
[out, retval] BSTR * strVersion);
Parameters
strVersion
BSTR of version.
Remarks
Read/Write. A string representing the version. The default value is "1.0".

Return Values
S_OK
Returned if no errors are reported.
See Also
Applies to: IMXWriter Interface
coolzdp 2005-12-21
  • 打赏
  • 举报
回复
在使用Com的Dispatch指针时,如果不使用COM智能指针,容易出现的错误。

  2.1:忘记在所有出口释放指针。
  
  如:

IXMLDOMDocument *pDoc = NULL;
CoCreateInstance(...)
……
pDoc->Release();

  错误:如果中间代码发生异常,则pDoc未能正常释放,造成内存泄露。

  2.2:重复使用同一指针变量,导致中间生成的Dispatch指针未能释放。

IXMLDOMNode *pNode = NULL;
if(FAILED(pDoc->selectSingleNode(_bstr_t("Workbook"), &pNode)) || pNode==NULL)
throw(_T("selectSingleNode failed!"));
if(FAILED(pDoc->selectSingleNode(_bstr_t("Workbook"), &pNode)) || pNode==NULL)
throw(_T("selectSingleNode failed!"));

  错误:pNode未释放就开始第二次调用,造成内存泄露。或者类似pNode = pNode2的这种写法,也随手就出问题了。必须调用if(pNode) {pNode->Release();pNode=NULL;}

  3:使用MFC提供的Com智能指针解决上述问题。

  注意:可通过查看源码,看到#import生成的智能指针的原型是_com_ptr_t。

  3.1:

IXMLDOMDocumentPtr docPtr = NULL;
docPtr.CreateInstance(...)
……

  这下不会有问题了,因为docPtr在析构时会有正确的释放处理。

  3.2:

IXMLDOMNodePtr nodePtr = NULL;
if(FAILED(pDoc->selectSingleNode(_bstr_t("Workbook"), &nodePtr)) || nodePtr==NULL)
throw(_T("selectSingleNode failed!"));
if(FAILED(pDoc->selectSingleNode(_bstr_t("Workbook"), &nodePtr)) || nodePtr==NULL)
throw(_T("selectSingleNode failed!"));

  不会出错了,因为_com_ptr_t重载了&操作符,在取指针时,有如下操作,嘿。

Interface** operator&() throw()
{
 _Release();
 m_pInterface = NULL;
 return &m_pInterface;
}

  3.3: nodePtr = nodePrt2 ,也不会有问题:

  仔细查看源码,在=操作符中会调用Attach,而Attach的做法是:会先调用_Release();

  3.4:再看看值传递:拷贝构造函数如下

template<> _com_ptr_t(const _com_ptr_t& cp) throw()
: m_pInterface(cp.m_pInterface)
{
 _AddRef();
}

  嗯,也不会有问题。

  3.5:最后我们也总结一下使用COM智能指针时的注意事项:

  ·不要在Com智能指针的生命期如果在::CoUninitailize之后,那请在调用::CoUninitailize之前,强制调用MyComPtr = NULL;达到强制释放的目的。否则会出错。

  ·不要混用智能指针和普通Dispatch指针,不要调用MyComPtr->Release(),这违背智能指针的原意,会在析构时报错。

  4:使用ATL提供智能指针:CComPtr或是CComQIPtr.

  如果不使用MFC框架,要自已包装IDispatch,生成智能指针,还可以使用ATL提供的智能指针。查看源码,并参照《深入解析ATL》一书,发现实现与_com_ptr_t大同小异,效果一致。
coolzdp 2005-12-21
  • 打赏
  • 举报
回复
楼主没看明白,
就是说如果使用了IXMLDOMDocumentPtr,IXMLDOMNodePtr
代替IXMLDOMDocument *,IXMLDOMNode *,
则不用自己释放资源。

msxml sdk上的例子这两种都用了

如这个例子就用的职能指针,自动释放资源
#include <tchar.h>
#import "msxml3.dll"
using namespace MSXML2;

inline void TESTHR( HRESULT _hr )
{ if FAILED(_hr) throw(_hr); }

void XMLDOMNodeSample()
{
try {
IXMLDOMDocumentPtr docPtr;
IXMLDOMNodePtr DOMNodePtr;

//init
TESTHR(docPtr.CreateInstance(_T("Msxml2.DOMDocument")));

VARIANT vtTemp;

vtTemp.vt=VT_I2;
vtTemp.iVal = 1; //NODE_ELEMENT
// load a document
_variant_t varXml(_T("c:\\book.xml"));
_variant_t varOut((bool)TRUE);
varOut = docPtr->load(varXml);
if ((bool)varOut == FALSE)
throw(0);
MessageBox(NULL, _bstr_t(docPtr->xml), _T("Original Document"), MB_OK);
DOMNodePtr = docPtr->createNode(vtTemp, _T("VIDEOS"), "");
docPtr->documentElement->appendChild(DOMNodePtr);
MessageBox(NULL, _bstr_t(docPtr->xml), _T("New Document"), MB_OK);

} catch(...)
{
MessageBox(NULL, _T("Exception occurred"), _T("Error"), MB_OK);
}
}
int main()
{
TESTHR(::CoInitialize(NULL));
XMLDOMNodeSample();
::CoUninitialize();
return 0;
}


这个例子就没用,要手动释放,最后的注释也强调了这一点
#import "msxml3.dll"
using namespace MSXML2;

#define CHECK_AND_RELEASE(pInterface) \
if(pInterface) \
{\
pInterface->Release();\
pInterface = NULL;\
}\

#define RELEASE(pInterface) \
{\
pInterface->Release();\
pInterface = NULL;\
}\

_variant_t varValue;
BSTR bstrAttributeName = ::SysAllocString(_T("dateCreated"));
IXMLDOMElement *pIXMLDOMElement = NULL;
IXMLDOMDocument *pIXMLDOMDocument = NULL;
HRESULT hr;

try
{
// Initialize pIXMLDOMDocument and load an
// XML file into it.
// Get the document root.
hr = pIXMLDOMDocument->get_documentElement( &pIXMLDOMElement);
SUCCEEDED(hr) ? 0 : throw hr;
if(pIXMLDOMElement)
{
varValue = _T("year 2000");
hr = pIXMLDOMElement->setAttribute(bstrAttributeName, varValue);
SUCCEEDED(hr) ? 0 : throw hr;

hr = pIXMLDOMElement->getAttribute(bstrAttributeName, &varValue);
SUCCEEDED(hr) ? 0 : throw hr;

if(varValue.vt != VT_NULL)
{
::MessageBox(NULL, _bstr_t(varValue), bstrAttributeName, MB_OK);
bResult = TRUE;
}
RELEASE(pIXMLDOMElement);
}
::SysFreeString(bstrAttributeName);
bstrAttributeName=NULL;
}
catch(...)
{
if(bstrAttributeName)
{
::SysFreeString(bstrAttributeName);
bstrAttributeName = NULL;
}
CHECK_AND_RELEASE(pIXMLDOMElement);
DisplayErrorToUser();
}
// Release pIXMLDOMDocument when finished with it.


楼主既然用了智能指针,就不要加这个了。多此一举
#define RELEASE(pInterface) \
{\
pInterface->Release();\
pInterface = NULL;\
}\

3,055

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC HTML/XML
社区管理员
  • HTML/XML社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧