2

全部,

这是我的代码

//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 - 如果它 <= 16407 一切正常。

编辑2:

罗迪是对的 - 我错过了那_bstr_t是一门课......

敲响任何铃铛?

干杯

4

4 回答 4

4

尝试更换

 BSTR Markup;

 bstr_t Markup;

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

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

于 2008-11-27T17:46:54.297 回答
1

好吧,我认为帕特里克是对的。我使用了您的代码并制作了一个名为 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。显然,您可以使用此代码进行更多测试,看看接下来会发生什么。

于 2008-11-27T18:54:00.777 回答
1

但是,我不精通这个特定的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

看看这是否有所作为。

于 2008-11-27T20:21:25.233 回答
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).
于 2008-12-05T13:52:20.087 回答