【问题标题】:MSXML2::IXMLDOMDocument2Ptr->GetXML() messing up my string!MSXML2::IXMLDOMDocument2Ptr->GetXML() 弄乱了我的字符串!
【发布时间】:2008-12-11 07:35:24
【问题描述】:

全部,

这是我的代码

//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; 

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

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

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

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

有什么建议吗?

编辑1:

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

EDIT2:

Roddy 是对的 - 我错过了 _bstr_t 是一个类...

铃响了吗?

干杯

【问题讨论】:

  • 重读我的帖子。除非您 100% 了解它的工作原理,否则您需要完全放弃 BSTR。
  • 您能否建议一段代码来实现您的解决方案,以便我通过示例来理解?

标签: c++ msxml


【解决方案1】:

尝试替换

 BSTR Markup;

与

 bstr_t Markup;

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

注意:您的“SuperMarkup”没有按照我的建议进行。同样,BSTR 只是一个指针,并不“拥有”它所指向的内容。另一方面,bstr_t 确实如此。我认为您的 GetXML() 函数正在返回一个 bstr_t,然后在超出范围时将其删除,使您的 BSTR 指向不再有效的内存。

【讨论】:

  • 我试过这个:bstr_t superMarkup = bstr_t(markup);然后在 LoadXML 调用中使用 superMarkup 而不是标记。没有任何改变!
  • 有 2 个变量,一个 bstr_t initialXML 和一个 bstr_t returnedXML。仅将每个变量用于一个目的。
  • 如果您不完全理解 BSTR 和 bstr_t(因此,谁——如果有人——拥有包含 GetXML 结果的内存),它可能也取决于月相。我无法提供比这更多的帮助了。
  • 即使我理解 BSTR bstr_t 并且你想要它仍然没有意义,如果大小正好低于 16407,它仍然可以正常工作
  • 无论如何,我确实尝试用 bstr_t 替换 BSTR,如果大小低于那个幻数,它就可以正常工作,与我的原始代码完全相同
【解决方案2】:

好的,我认为帕特里克是对的。我使用了您的代码并制作了一个名为 getxmltest 的快速 ATL EXE 项目。 我在#include 指令之后添加了这一行

#import "MSXML3.DLL"

删除了注册组件的构建后事件,因为我不想从 exe 公开任何组件,但只引用了所有 ATL 标头和库,并将以下代码添加到 _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。显然,您可以使用此代码进行更多测试,看看接下来会发生什么。

【讨论】:

  • 如果尺寸 > 16407,你能重现我的问题吗(参见 OP 中的编辑)
  • 我在我的代码中添加了几行代码,以便将元素动态添加到 xml 中,从而毫无问题地获得长度为 160013 字节的 xml。我会在下面的新回复中发布最终代码
【解决方案3】:

我对这个特定的 xml 库并不精通,但是:

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

这个过程似乎可能会使您刚刚收到的字符串无效。您会注意到 Eugenio Miró 在他的示例中没有犯这个错误,因为他分配了一个不同的变量来保存输入 (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

看看这是否会有所作为。

【讨论】:

  • 感谢您指出这一点,但我不明白您对 pXMLDoc 的考虑!
【解决方案4】:

这是我之前写的代码,做了一点修改,添加了 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).

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-03-14
    • 1970-01-01
    • 2014-06-15
    • 2019-12-11
    • 2014-03-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多