问题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(); }

解决方案 »

  1.   

    在使用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大同小异,效果一致。
      

  2.   

    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. 
    Res
    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
      

  3.   

    就是说,我在循环中每次都得释放了? 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();
    }
      

  4.   

    楼主没看明白,
    就是说如果使用了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;\
       }\
      

  5.   

    过会儿就好了
    CSDN的服务器的刷新机制有问题