2008-11-27 1 views
1

Все,MSXML2 :: IXMLDOMDocument2Ptr-> GetXML() испортить мою строку!

это мой код

//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, я все равно получаю мусор.

На данный момент, если я пытаюсь присвоить искаженный указатель на другой указатель будет TRow ошибки:

Attempted to restore write protected memory. this is often an indication that other memory is corrupted.

Любого предложение?

EDIT1:

я узнал, что это происходит в связи с размером строки XML. Если это происходит в данной строке XML, и я уменьшаю размер (сохраняя ту же схему), он будет работать нормально. Похоже, MSXML2 :: DOMDocument40 имеет ограничение по размеру? Подробно это происходит, если у меня есть более 16407 символов. У меня есть еще один GetXML, который будет извлекать RUBBISH - если это < = 16407, все работает нормально.

EDIT2:

Родди был прав - я пропускал, что _bstr_t класс ...

кольца любой колокол?

Приветствия

+0

Перечитайте мое сообщение. Вам нужно полностью обрезать BSTR, если вы не поймете 100%, как это работает. – Roddy 2008-11-28 10:56:09

+0

вы можете предложить фрагмент кода для реализации вашего решения, чтобы я мог понять пример? – JohnIdol 2008-12-04 17:14:41

ответ

4

Попробуйте заменить

BSTR Markup; 

с

bstr_t Markup; 

BSTR является в значительной степени немой указатель, и я думаю, что возвращение результат GetXML() преобразовывается к временный, который затем уничтожается к тому времени, когда вы его увидите. bstr_t обертывает это с помощью некоторой умной стрелки ...

Примечание: ваша вещь «SuperMarkup» НЕ выполняла то, что я предлагал. Опять же, BSTR - это просто указатель и не «владеет» тем, на что он указывает. bstr_t, с другой стороны. Я думаю, что ваша функция GetXML() возвращает bstr_t, который затем удаляется по мере того, как он выходит из области видимости, оставляя ваш BSTR, указывающий на память, более недействительным.

+0

Я пробовал: bstr_t superMarkup = bstr_t (разметка); затем используется супермаркинг вместо разметки в вызове LoadXML. Ничего не изменилось! – JohnIdol 2008-11-27 20:02:37

+0

Имейте 2 переменные, bstr_t initialXML и bstr_t returnXML. Используйте только одну переменную для одной цели. – Patrick 2008-11-28 11:02:51

1

Хорошо, я думаю, Патрик прав. Я взял ваш код и сделал быстрый проект ATL EXE с именем getxmltest. я добавил эту линию после директивы #include

#import "MSXML3.DLL" 

удалил событие после сборки, который регистрирует компонент, потому что я не хочу подвергать какой-либо компонент из еха, но только все 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). 

Где мы может видеть строку, в которую мы ввели первоначально. Я не добавлял никакой логики в код, потому что, хотя этого было достаточно, чтобы отобразить полученный xml после обработки его с помощью механизма MSXML. Очевидно, вы можете сделать еще несколько тестов с помощью этого кода и посмотреть, что произойдет дальше.

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 

и посмотреть, если это делает разницу.

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