CComPtr<::IXMLDOMDocument>spXMLDoc;
HRESULT hr = spXMLDoc->load(varFile, &result);
// изменение
spXMLDoc->save(varFile); // сохранение
Кодировка XML
Открываю этот файл своей программой при помощи MSXML DOM, редактирую и сохраняю:
Код:
в результате файл сохраняется в кодировке UTF-8, и сторонняя прога не может с ним правильно работать.
Как задать кодировку UCS-2 средствами MSXML DOM ?
Давненько я не пользовался DOM'ом но если память не изменяет - Получить XMLDOMProcessingInstruction и установить (если есть) или создать атрибут encoding c соответствующим содержанием а уж потом сохранить... Помница помогало (тогда боролся за UTF-8), и это был аж 3 MSXML...
Код:
spXMLDoc->createProcessingInstruction(L"xml", L"version=\"1.0\"", &spPrInst);
spPrInst->QueryInterfaceIID_IXMLDOMElement, (void**)&spEl);
spEl->setAttribute(L"encoding", _variant_t(L"UCS-2"));
spPrInst->QueryInterfaceIID_IXMLDOMElement, (void**)&spEl);
spEl->setAttribute(L"encoding", _variant_t(L"UCS-2"));
однако spEl ==NULL
хотя если передавать интерфейс в IXMLDOMNode, то он передается, но в IXMLDOMElement из него опять ==NULL.
как то странно работает, если учесть что схема с передачей интерфейса от нода к элементу во вложенных нодах работает на ура.
Код:
spXMLDoc->createProcessingInstruction(L"xml", L"version=\"1.0\" encoding=\"UCS-2\"", &spPrInst);
Цитата: 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]
[/FONT]bstrText == version="1.0" encoding="UCS-2"
PS а что про UCS-2 вообще написано в доках, мож он просто не поддерживается на запись, хотя если чИтает, не совсем понятно...
PSS кстати после общения с представителями Microsoft 3 года назад как раз по поводу проблемы с MSXML и после их рекомендации я был вынужден отказаться от него в пользу Xerces от Appache... Хотя сейчас в большинстве своем пользуюсь своим же парсером...
собственно остается один вариант: грузить из файла в строку, заменять первую строку (вставлять encoding="UCS-2") и делать IXMLDOMDocument::loadXML(...)
Заранее спасибо...
Код:
<?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>
<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);
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);
Хорошо, взял...
в обоих кодировках она нормально пишется, во всяком случае нотпад++ нормально конвертит из одной в другую
Код:
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;
}
{
//****
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 это совсем не то что видется, так как это собственно простой уникод...
Успехов...
Код:
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);
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);
:)
Но вот в чем проблема, а если в инструкции уже есть кодавая страница, то надо делать еще и ее анализ и изменение, тады и код увеличится :) Хотя мой вариант не идеален - идеальным возможно он будет с добавлением анализа что первый узел это инструкция, а так если она не первая (такое допускается в MSXML по крайней мере) - надо делать ее поиск - то усе, хана документу :)
Кстати если неправильно задать кодовую страницу записать то он запишется, только размер файла выхода будет 0...
Код:
<?xml version="1.0"?>
я так понимаю, это внутренний XML-овский флаг, т.е. исходный файл можно сохранить в любой кодировке - не обязательно через DOM
Вот что интересно - видимо при нахождении указания кодировки он ее убирает в случае если мы получаем данным методом, так как при сохранении она остается без изменений - только что проверил...
[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]
Ну чтож буду знать на будущее :)