Кодування в XML (движок msxml)
Нічого не розумію. Створюю:
FEngine := CreateOLEObject("MSXML2.DOMDocument") as IXMLDOMDocument; FEngine.Async := false ;
if FEngine.parseError.errorCode <> 0 then raise Exception.Create(FEngine.parseError.reason);
Коли зчитую значення ноди Val:
TextNode := selectSingleNode("text()") as IXMLDOMText ; ShowMessage(TextNode.data);
Отримуємо кодування Windows-1251.
А якщо xml такий:
то отримуємо абракадабру. Таке відчуття, що msxml взагалі ігнорує вказівку кодування в XML-файлі. Чому він коректно не перетворює будь-яке вказане кодування до свого WideString (utf-16), звідки я вже читав би завжди також коректно?
І що робити в цій ситуації, адже я хочу вміти обробляти як XML з windows-1251, так і з utf-8.
> то отримуємо абракадабругм. garbage in, garbage out? відкрий свою иксемельку чимось крім своєї проги і перевір, сміття там чи потрібний рядок.
> Таке відчуття, що msxml взагалі ігнорує вказівку кодування > у xml-файлі
> гм. garbage in, garbage out? відкрий свою іксемільку чим- > то крім своєї проги і перевір, сміття там чи потрібний рядок.все ок там із кодуванням.
Але я помітив жахливу дивина. Якщо зберегти текст у файл і завантажити файл методом load, все дуже чудово.
А ось якщо як я написав вище – динамічно за допомогою методу loadXML – то з кодуванням проблеми. Що за річ. Тепер відчуття, що msxml плює на вказівку кодування при ДИНАМІЧНОМУ завантаженні xml'я.
до кодувань, з якими працює MSXML і до того, що внутрішнє уявлення в нього Unicode.
Ігоре Шевченко, ну а що толку, якщо при вказівці кодування: utf-8 в заголовку XML приДИНАМІЧНОМУ завантаженні - двигун не перетворює його на правильний формат?
Точніше, як я розумію, при динамічному завантаженні XML двигун просто плює на вказівку кодування і вважає її windows-1251 (що взагалі розходиться зі стандартом, за яким дефолтне кодування XML це utf-8). І відповідним чином перетворює на unicode, але оскільки припущення про початкове кодування неправильне - отримуємо фігню.
Питання - що робити млинець.
> Точніше, як я розумію, за динамічного завантаження XML двигун > просто плює на вказівку кодування та вважає її windows- > 1251
loadXML() метод буде працювати тільки з UTF-16 або UCS-2 encodings
Давно вже пора забути про Windows-1251. А то можна буде 866-кодову сторінку приплести. Або того гірше за КОІ-7. Це все минуле століття.
> loadXML() метод буде працювати тільки з UTF-16 або UCS-2 > encodingsопа, дійсно. Млинець дурість яка. Цікаво, чим обґрунтовано.
Справа в тому, що XML я отримую по мережі, мені б його зручно розпарсувати за допомогою msxml, а тут така підстава.
А є інший валідний спосіб, крім записувати щоразу XML у темпову директорію і нацьковувати вже на нього двигун msxml? (
> А є інший валідний спосіб, крім записувати кожен . раз XML у темпову директорію та нацьковувати вже на нього > двигун msxml? (
Якщо у нього відоме кодування UTF-8, то перетворювати на UTF-16 стандартним викликом Utf8ToUnicode, наприклад
> > Якщо у нього відоме кодування UTF-8так у тому й річ, що хочеться універсалізації та стандартизації.
Щоб не важливо, як відповідав віддалений сервіс, а парсилося завжди правильно. За фактом зараз буває чиutf-8, або windows-1251. Причому хочеться стандартизації за правилами XML, тобто якщо кодування не вказане - значить, воно дефолтне utf-8. Знову MS винайшли свій велосипед млинець.
Звичайно, можна милиці прилаштовувати, щоб самому відокремлювати тег кодування, далі перетворювати код XML і вже потім згодовувати його движку msxml, але даний варіант мене теж чомусь не тішить.
завантажуй із потоку (IStream), а не через loadXml(), тоді кодування буде враховуватися.
procedure TForm1.Button1Click(Sender: TObject); const s=" "+ " "+ " Рядок "+ " "; var FEngine:variant; begin FEngine := CreateOLEObject("MSXML2.DOMDocument") as IDispatch; FEngine.Async := false ; FEngine.load(TStreamAdapter.Create(TStringStream.Create(s),soOwned) as IStream); if FEngine.parseError.errorCode <> 0 then raise Exception.Create( FEngine.parseError.reason ); end;
> Знову MS винайшли свій велосипед млинець.Знову MS винен млинець. Користувався б не MSXML2.DOMDocument, а якимось іншим об'єктом, якщо ти думаєш, що там буде краще млинець.
Кодування в пролозі впливає на серіалізований документ. Поки цього немає, з кодуванням в пролозі можна взагалі не морочитися. Що у вузол записали, то і вважали
var xdoc ,xdoc1: IXMLDOMDocument2; begin xdoc := CoDOMDocument.Create; xdoc1 := CoDOMDocument.Create; xdoc.loadXML(" "); ShowMessage(xdoc.xml);//кодування вказане в пролозі зникло xdoc1.loadXML(xdoc.xml); // тим не менше воно працює ShowMessage (xdoc1.xml);
якщо xdoc зберегти у файл, кодування в пролозі з'явиться. Але якщо зберегти файл просто xdoc.xml.текст , то файл не завантажиться.
Або краще навіть так:
ShowMessage(xdoc.xml);//кодування вказане впролозі зникла
> Справа в тому, що XML я отримую по мережі, мені б його зручно розпарсувати за допомогою msxml, а тут така підстава. > А є інший валідний спосіб, крім записувати щоразу XML у темпову директорію і нацьковувати вже на нього двигун msxml? ( просто load(. ) із зазначенням url "з мережі"?)
Slym, супер, зашибісь. Дякую