MSXML2 :: IXMLDOMDocument2Ptr-> GetXML()搞乱了我的字符串!

时间:2008-11-27 16:28:01

标签: c++ msxml

所有

这是我的代码

//declare string pointer
BSTR markup;

//initialize markup to some well formed XML <-

//declare and initialize XML Document
MSXML2::IXMLDOMDocument2Ptr pXMLDoc;
HRESULT hr;
hr = pXMLDoc.CreateInstance(__uuidof(MSXML2::DOMDocument40));
pXMLDoc->async = VARIANT_FALSE;
pXMLDoc->validateOnParse = VARIANT_TRUE;
pXMLDoc->preserveWhiteSpace = VARIANT_TRUE;    

//load markup into XML document
vtBoolResult = pXMLDoc->loadXML(markup);

//do some changes to the XML file<-

//get back string from XML doc
markup = pXMLDoc->Getxml(); //<-- this retrieves RUBBISH

此时我的字符串被破坏了(开头只有几个汉字然后是垃圾)。看起来像编码问题。

我也尝试了以下内容:

_bstr_t superMarkup = _bstr_t(markup);

//did my stuff

superMarkup = pXMLDoc->Getxml();

markup = superMarkup; 

但我仍然得到相同的结果。

即使我在不​​更改xml文档中的任何内容的情况下调用GetXML(),我仍然会得到垃圾。

此时如果我尝试将损坏的指针分配给另一个指针,它将抛出一个错误:

  

尝试恢复写保护   记忆。这通常是一个迹象   其他内存已损坏。

有什么建议吗?

EDIT1:

我发现这与XML字符串的大小有关。 如果它发生在给定的XML字符串上并且我减小了大小(保持相同的模式)它将正常工作。看起来像MSXML2 :: DOMDocument40有大小限制? 详细地说,如果我有超过16407个字符,就会发生这种情况。我还有一个GetXML将检索RUBBISH - 如果它是&lt; = 16407一切正常。

EDIT2:

罗迪是对的 - 我错过了_bstr_t是一个班级......

敲响铃声?

干杯

4 个答案:

答案 0 :(得分:4)

尝试替换

 BSTR Markup;

 bstr_t Markup;

BSTR几乎是一个愚蠢的指针,我认为GetXML()的返回结果正在转换为临时值,然后在你看到它时就会被破坏。 bstr_t用一些智能指针的优点包装它......

注意:你的“SuperMarkup”事情并不符合我的建议。同样, BSTR只是一个指针,并且不“拥有”它所指向的内容。另一方面,bstr_t。我认为你的GetXML()函数正在返回一个bstr_t,然后当它超出范围时被删除,让你的BSTR指向不再有效的内存。

答案 1 :(得分:1)

好的,我认为帕特里克是对的。我拿了你的代码,做了一个名为getxmltest的快速ATL EXE项目。 我在#include指令

之后添加了这一行
#import "MSXML3.DLL"

删除了注册组件的post-build事件,因为我不想暴露exe中的任何组件,但只有所有ATL头文件和libs已经引用,并将以下代码添加到_tWinMain

extern "C" int WINAPI _tWinMain(HINSTANCE /*hInstance*/, HINSTANCE /*hPrevInstance*/, 
                                LPTSTR /*lpCmdLine*/, int nShowCmd)
{
    CoInitialize(NULL);
    {
        //declare string pointer
        _bstr_t                     markup;
        //initialize markup to some well formed XML <-
        //declare and initialize XML Document
        MSXML2::IXMLDOMDocument2Ptr pXMLDoc;
        HRESULT                     hr              = pXMLDoc.CreateInstance(__uuidof(MSXML2::DOMDocument));

        pXMLDoc->async              = VARIANT_FALSE;
        pXMLDoc->validateOnParse    = VARIANT_TRUE;
        pXMLDoc->preserveWhiteSpace = VARIANT_TRUE;    

        //load markup into XML document
        VARIANT_BOOL                vtBoolResult    = pXMLDoc->loadXML(L"<XML></XML>");

        //do some changes to the XML file<-
        //get back string from XML doc
        markup = pXMLDoc->Getxml(); //<-- this retrieves RUBBISH (not anymore...)
        ATLTRACE("%S", (BSTR)markup.GetBSTR());
    }
    CoUninitialize();
    return _AtlModule.WinMain(nShowCmd);
}

得到的跟踪线如下......

'getxmltest.exe': Loaded 'C:\Windows\winsxs\x86_microsoft.windows.common-controls_6595b64144ccf1df_6.0.6001.18000_none_5cdbaa5a083979cc\comctl32.dll'
<XML></XML>
'getxmltest.exe': Unloaded 'C:\Windows\SysWOW64\msxml3.dll'
The program '[6040] getxmltest.exe: Native' has exited with code 0 (0x0).

我们可以看到最初输入的字符串.. 我没有在代码中添加任何逻辑,因为我虽然这足以在使用MSXML引擎处理后显示生成的xml。显然,您可以使用此代码进行更多测试,看看接下来会发生什么。

答案 2 :(得分:1)

我不熟悉这个特定的 xml库,但是:

这里要注意的是原始问题在检索结果时覆盖了变量'markup'。许多XML解析器返回指向初始输入(即标记)的指针,因此当您用输出替换它时,您还会删除XML解析器的输入。

此过程似乎可能会使您刚收到的字符串无效。你会注意到EugenioMiró在他的例子中没有犯这个错误,因为他分配了一个不同的变量来保存输入(pXMLDoc)。

您可能想做的快速测试是更改

//get back string from XML doc
markup = pXMLDoc->Getxml(); //<-- this retrieves RUBBISH

//get back string from XML doc
BSTR output = pXMLDoc->Getxml(); //<-- perhaps this doesn't

看看是否有所作为。

答案 3 :(得分:1)

这是我之前编写的代码,稍加修改,增加了20000个'子元素':)它运行良好。

extern "C" int WINAPI _tWinMain(HINSTANCE /*hInstance*/, HINSTANCE /*hPrevInstance*/, 
                                LPTSTR /*lpCmdLine*/, int nShowCmd)
{
    CoInitialize(NULL);
    {
        //declare string pointer
        _bstr_t                           markup;
        //initialize markup to some well formed XML <-
        //declare and initialize XML Document
        try {
            MSXML2::IXMLDOMDocument2Ptr   pXMLDoc;
            HRESULT                       hr              = pXMLDoc.CreateInstance(__uuidof(MSXML2::DOMDocument));    
            pXMLDoc->async                = VARIANT_FALSE;
            pXMLDoc->validateOnParse      = VARIANT_TRUE;
            pXMLDoc->preserveWhiteSpace   = VARIANT_TRUE;    

            //load markup into XML document
            VARIANT_BOOL                  vtBoolResult    = pXMLDoc->loadXML(L"<XML></XML>");

            for (int i = 0; i < 20000; i++) {
                MSXML2::IXMLDOMNodePtr    node            = pXMLDoc->createNode(_variant_t("element"), _bstr_t("child"), _bstr_t(""));

                if (node)
                    pXMLDoc->documentElement->appendChild(node);
            }

            //do some changes to the XML file<-
            //get back string from XML doc
            markup = pXMLDoc->Getxml(); //<-- th
            ATLTRACE("XML lenght = %d, xml=%S\n", markup.length(), (BSTR)markup.GetBSTR());
        } catch(_com_error e) {
            ATLTRACE("error = %S\n", (BSTR)e.ErrorMessage());
        }
    }
    CoUninitialize();
    return _AtlModule.WinMain(nShowCmd);
}

这会在调试器中生成1024输出行,但如果您愿意,这可以轻松地将xml打印到stdoutput。 这是我到目前为止的输出

'getxmltest.exe': Loaded 'C:\Windows\winsxs\x86_microsoft.windows.common-controls_6595b64144ccf1df_6.0.6001.18000_none_5cdbaa5a083979cc\comctl32.dll'
XML lenght = 160013, xml=<XML><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><child/><'getxmltest.exe': Unloaded 'C:\Windows\SysWOW64\msxml3.dll'
The program '[4884] getxmltest.exe: Native' has exited with code 0 (0x0).