Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Кодировка XML

11
05 ноября 2008 года
oxotnik333
2.9K / / 03.08.2007
Есть XML файл, который создается сторонней программой и меет кодировку UCS-2.
Открываю этот файл своей программой при помощи MSXML DOM, редактирую и сохраняю:
 
Код:
CComPtr<::IXMLDOMDocument>spXMLDoc;
HRESULT hr = spXMLDoc->load(varFile, &result);
// изменение
spXMLDoc->save(varFile); // сохранение


в результате файл сохраняется в кодировке UTF-8, и сторонняя прога не может с ним правильно работать.
Как задать кодировку UCS-2 средствами MSXML DOM ?
342
05 ноября 2008 года
Yos
209 / / 21.06.2003
Давненько я не пользовался DOM'ом но если память не изменяет - Получить XMLDOMProcessingInstruction и установить (если есть) или создать атрибут encoding c соответствующим содержанием а уж потом сохранить... Помница помогало (тогда боролся за UTF-8), и это был аж 3 MSXML...
11
05 ноября 2008 года
oxotnik333
2.9K / / 03.08.2007
что бы установить атрибут encodingнадо передать интерфейс с IXMLDOMProcessingInstruction на IXMLDOMElement
 
Код:
spXMLDoc->createProcessingInstruction(L"xml", L"version=\"1.0\"", &spPrInst);
spPrInst->QueryInterfaceIID_IXMLDOMElement, (void**)&spEl);
spEl->setAttribute(L"encoding", _variant_t(L"UCS-2"));

однако spEl ==NULL
хотя если передавать интерфейс в IXMLDOMNode, то он передается, но в IXMLDOMElement из него опять ==NULL.
как то странно работает, если учесть что схема с передачей интерфейса от нода к элементу во вложенных нодах работает на ура.
342
05 ноября 2008 года
Yos
209 / / 21.06.2003
А если на узле (IXMLDOMNode) сразу сделать setAttribute? - хотя скорее всего не прокатит, можно попробовать по другому:
 
Код:
spXMLDoc->createProcessingInstruction(L"xml", L"version=\"1.0\" encoding=\"UCS-2\"", &spPrInst);
так как согласно докам не запрещено...
11
05 ноября 2008 года
oxotnik333
2.9K / / 03.08.2007
Цитата: Yos
А если на узле (IXMLDOMNode) сразу сделать setAttribute? - хотя скорее всего не прокатит, можно попробовать по другому:
 
Код:
spXMLDoc->createProcessingInstruction(L"xml", L"version=\"1.0\" encoding=\"UCS-2\"", &spPrInst);
так как согласно докам не запрещено...


как только не извращался, но как была 1-я строка в файле

Цитата:

<?xml version="1.0"?>

так и остается
хотя в отладке

 
Код:
spPrInst->get_text(&bstrText)[FONT=monospace];
[/FONT]
[FONT=monospace]
[/FONT]bstrText == version="1.0" encoding="UCS-2"
342
05 ноября 2008 года
Yos
209 / / 21.06.2003
Такс, я кажется понял про так и остается хотя в отладке нужно не создать новый а получить уже существующий и его поправить, или удалить существующий и добвавить новый...

PS а что про UCS-2 вообще написано в доках, мож он просто не поддерживается на запись, хотя если чИтает, не совсем понятно...

PSS кстати после общения с представителями Microsoft 3 года назад как раз по поводу проблемы с MSXML и после их рекомендации я был вынужден отказаться от него в пользу Xerces от Appache... Хотя сейчас в большинстве своем пользуюсь своим же парсером...
11
06 ноября 2008 года
oxotnik333
2.9K / / 03.08.2007
собственно остается один вариант: грузить из файла в строку, заменять первую строку (вставлять encoding="UCS-2") и делать IXMLDOMDocument::loadXML(...)
342
06 ноября 2008 года
Yos
209 / / 21.06.2003
Уважаемый oxotnik333, если Вас не затруднит, выложите XML файл куда нибудь и дайте ссылку для скачивания, есть свободное время - интересно поколдовать, о ней (кодировке) почитал, но никогда не встречал, хочется посмотреть "вживую" :) о результатах доложу, а куда и как решу походу...

Заранее спасибо...
11
06 ноября 2008 года
oxotnik333
2.9K / / 03.08.2007
с файловыми архивами не дружу, текст файла:
Код:
<?xml version="1.0"?>
<mstns:materials xmlns:mstns="http://www.solidworks.com/sldmaterials" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" xmlns:sldcolorswatch="http://www.solidworks.com/sldcolorswatch" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <curves id="curve0">
        <point x="1.000000" y="1.000000"/>
        <point x="2.000000" y="1.000000"/>
        <point x="3.000000" y="1.000000"/>
    </curves>
    <classification name="Стали углеродистые">
        <material name="Ст3сп ГОСТ 16523-97">
            <shaders>
                <pwshader name="сталь"/>
                <cgshader name="texture"/>
                <swtexture path="images\textures\metal\cast\cast_fine.jpg"/>
            </shaders>
            <swatchcolor RGB="686b6e">
                <sldcolorswatch:Optical Ambient="0.520000" Transparency="0.000000" Diffuse="0.800000" Specularity="1.000000" Shininess="0.400000" Emission="0.000000"/>
            </swatchcolor>
            <xhatch name="ISO (Сталь)" angle="0.000000" scale="1.000000"/>
            <physicalproperties>
                <DENS displayname="Плотность" value="7830.000000"/>
            </physicalproperties>
        </material>
    </classification>
</mstns:materials>

в нотпаде++ можно задать любую кодировку

ЗЫ: переделал через ж...

 
Код:
hr = spXMLDoc->load(varFile, &sucss);
    BSTR bstrXMLstr;
    spXMLDoc->get_xml(&bstrXMLstr);
    wstring XMLstring(bstrXMLstr);
    f_data = (int)XMLstring.find_first_of(L"version=\"1.0\"");
    XMLstring.insert(f_data + 13, L" encoding=\"UCS-2\"");
    spXMLDoc->loadXML((BSTR)XMLstring.c_str(), &sucss);
//меняем что надо
    hr = spXMLDoc->save(varFile);
342
06 ноября 2008 года
Yos
209 / / 21.06.2003
А почему значения "Плотность" в частности написано корректно кирилицей, согласно того что почитал там такого быть не должно...

Хорошо, взял...
11
06 ноября 2008 года
oxotnik333
2.9K / / 03.08.2007
в обоих кодировках она нормально пишется, во всяком случае нотпад++ нормально конвертит из одной в другую
342
07 ноября 2008 года
Yos
209 / / 21.06.2003
Как обещал - вот код (сегодня с утреца нечего было делать)
Код:
int main(int Count, char ** pArguments)
{
 //****
 HRESULT            hr;

 IXMLDOMDocument  * pXMLDoc;
 IXMLDOMNode      * pXMLNode;

 IXMLDOMNode      * pFirst;
 IXMLDOMNode      * pOld;
 IXMLDOMNode      * pNew;

 IXMLDOMProcessingInstruction     * pXMLInstruction;

 VARIANT_BOOL       result;
 VARIANT            name;
 VARIANT            value;

 //...
 printf("START\n");
 CoInitialize(NULL);

 //
 printf("Initialize\n");
 hr = CoCreateInstance(CLSID_DOMDocument30,NULL,CLSCTX_INPROC_SERVER,IID_IXMLDOMDocument,(void**)&pXMLDoc);
 if( FAILED(hr) ) return 0;

 //
 printf("Load\n");
 VariantInit(&name);
 name.vt = VT_BSTR;
 name.bstrVal = SysAllocString(L"test.xml");
 hr = pXMLDoc->load(name,&result);
 if( FAILED(hr) ) return 0;

 //
 printf("1\n");
 hr = pXMLDoc->QueryInterface(IID_IXMLDOMNode,(void **)&pXMLNode);
 if( FAILED(hr) ) return 0;

 //
 printf("2\n");
 hr = pXMLNode->get_firstChild(&pFirst);
 if( FAILED(hr) ) return 0;

 //
 printf("3\n");
 hr = pXMLNode->removeChild(pFirst,&pOld);
 if( FAILED(hr) ) return 0;

 //
 printf("Create instruction\n");
 //hr = pXMLDoc->createProcessingInstruction(SysAllocString(L"xml"),SysAllocString(L"version=\"1.0\" encoding=\"WINDOWS-1251\""),&pXMLInstruction);
 //hr = pXMLDoc->createProcessingInstruction(SysAllocString(L"xml"),SysAllocString(L"version=\"1.0\" encoding=\"UTF-8\""),&pXMLInstruction);
 hr = pXMLDoc->createProcessingInstruction(SysAllocString(L"xml"),SysAllocString(L"version=\"1.0\" encoding=\"UCS-2\""),&pXMLInstruction);
 if( FAILED(hr) ) return 0;

 //
 printf("4\n");
 hr = pXMLNode->get_firstChild(&pFirst);
 if( FAILED(hr) ) return 0;

 //
 printf("Insert instruction\n");
 VariantInit(&value);
 value.vt = VT_DISPATCH;
 value.pdispVal = pFirst;
 hr = pXMLNode->insertBefore((IXMLDOMNode *)pXMLInstruction,value,(IXMLDOMNode **)&pNew);
 if( FAILED(hr) ) return 0;

 //
 printf("Save\n");
 VariantInit(&name);
 name.vt = VT_BSTR;
 name.bstrVal = SysAllocString(L"test_new.xml");
 hr = pXMLDoc->save(name);
 if( FAILED(hr) ) return 0;

 //...
 printf("END\n");
 CoUninitialize();

 return 0;
}


Выложил весь кодец, вдруг кому сгодится для изучения. Если вдруг будут требоваться пояснения всегда рад...

А по поводу что нотпад читает это так сказать не есть хорошо, так как соурс UCS-2 это совсем не то что видется, так как это собственно простой уникод...

Успехов...
11
07 ноября 2008 года
oxotnik333
2.9K / / 03.08.2007
собственно до того же самого додумался, но со строкой проще

 
Код:
hr = spXMLDoc->load(varFile, &sucss);
    BSTR bstrXMLstr;
    spXMLDoc->get_xml(&bstrXMLstr);
    wstring XMLstring(bstrXMLstr);
    f_data = (int)XMLstring.find_first_of(L"version=\"1.0\"");
    XMLstring.insert(f_data + 13, L" encoding=\"UCS-2\"");
    spXMLDoc->loadXML((BSTR)XMLstring.c_str(), &sucss);
//делаем что то
    hr = spXMLDoc->save(varFile);

:)
342
07 ноября 2008 года
Yos
209 / / 21.06.2003
Ну и отлично...

Но вот в чем проблема, а если в инструкции уже есть кодавая страница, то надо делать еще и ее анализ и изменение, тады и код увеличится :) Хотя мой вариант не идеален - идеальным возможно он будет с добавлением анализа что первый узел это инструкция, а так если она не первая (такое допускается в MSXML по крайней мере) - надо делать ее поиск - то усе, хана документу :)

Кстати если неправильно задать кодовую страницу записать то он запишется, только размер файла выхода будет 0...
11
07 ноября 2008 года
oxotnik333
2.9K / / 03.08.2007
кодовая страница не отображается методом get_xml(...) т.е. какая бы ни стояла кодировка, первая строка всегда будет
 
Код:
<?xml version="1.0"?>

я так понимаю, это внутренний XML-овский флаг, т.е. исходный файл можно сохранить в любой кодировке - не обязательно через DOM
342
07 ноября 2008 года
Yos
209 / / 21.06.2003
Вот что интересно - видимо при нахождении указания кодировки он ее убирает в случае если мы получаем данным методом, так как при сохранении она остается без изменений - только что проверил...
11
07 ноября 2008 года
oxotnik333
2.9K / / 03.08.2007
Вот что MSDN пишет
[quote=MSDN]
The xml property always returns a Unicode string. That is, the xml property for DOMDocument converts the document from its original encoding to Unicode. As a result, the original encoding attribute is removed. For example, <?xml version="1.0" encoding="UTF-8"?> appears in the xml property as follows.

Copy Code <?xml version="1.0"?>
If the original encoding was not removed by the xml property, the following line returns an error indicating the parser cannot switch from Unicode to UTF-8 encoding
[/quote]
342
07 ноября 2008 года
Yos
209 / / 21.06.2003
MSDN красавец, то что конвертит в уни я знал, но что он при этом еще и "превращает" описание кодовой страницы в свойство, да еще и динамически при создании и редактировании инструкции, для меня стало новостью...

Ну чтож буду знать на будущее :)
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог