• Тимохов Дима © (14.06.16 01:11) [0]
    Коллеги!

    1. Меня тут старшие товарищи пристыдили, что пользуюсь доморощенным парсером XML вместо проверенного временем MSXML. Полностью согласен!

    2. Сел читать про TXMLDocument. Какие-то локальные задачи на нем решал и ранее, но сейчас надо все по-серьезному (так называемый ЭДО наступает). Поэтому хочу изучить тему хорошо (как мастер дельфи ;-o).

    3. Вопрос даже не по TXMLDocument, а по современным источникам информации по Дельфи. Что читать? Что сейчас считается достоверным светочем информации по Дельфи?
      docwiki.embarcadero.com?
      docs.embarcadero.com?
      штатная справка (у меня до сих пор Delphi2007).
      доп. ресурсы?
  • Eraser © (14.06.16 03:27) [1]

    > Тимохов Дима ©   (14.06.16 01:11) 


    >
    > 1. Меня тут старшие товарищи пристыдили, что пользуюсь доморощенным
    > парсером XML вместо проверенного временем MSXML. Полностью
    > согласен!

    тут надо отдельно пояснить, что TXMLDocument - это не парсер. Это обертка над несколькими парсерами, пока их 3 штуки http://community.embarcadero.com/blogs/entry/setting-the-default-xml-dom-in-delphi-xe7-1

    что касается производительности, там где она действительно нужна используем nativexml, к сожалению, обертки для TXMLDocument у него пока нет.


    > Delphi2007

    в следующем году - 10 лет.
  • iop © (14.06.16 08:24) [2]
    Поэтому хочу изучить тему хорошо (как мастер дельфи ;-o).

    по сути главное отличие - поддержка xpath
    которая вместо навигационного подхода дает декларативный (sql-like) доступ к данным.
    а значит изучение темы сводится к двум методам selectsingleNode, selectNodes + синтаксис xpath
  • Dimka Maslov © (14.06.16 10:10) [3]
    Лично я пользуюсь доморощенным xml-парсером (не выбрасывать же его) в перемешку с родным маздайным IHTMLDocument, читать про который надо, как водится, в МСДНе.
  • DVM © (14.06.16 10:16) [4]

    > Тимохов Дима ©   (14.06.16 01:11) 


    > 1. Меня тут старшие товарищи пристыдили, что пользуюсь доморощенным
    > парсером XML вместо проверенного временем MSXML. Полностью
    > согласен!

    Я тоже иногда пользуюсь доморощенным парсером. Пусть он не умеет многого, но то, что мне нужно зато, он умеет как мне надо.
  • Тимохов Дима © (14.06.16 11:32) [5]
    1. NativeXML.

    1.1. Именно им и пользуюсь. Назвал его доморощенным в том смысле, что не общепринятый.

    1.2. Сейчас пользуюсь версией 2.26. Все было хорошо лет 10,  пока не встала четко задача с различными кодировками работать (до этого был только ANSI - его хватало для внутренних нужд).
    Начал разбираться, как он там умеет читать/писать в других кодировках...

    Но когда увидел код

       // Find correct encoding info
       for i := 0 to cBomInfoCount - 1 do
       begin
         if cBomInfo[i].Enc = FEncoding then
         begin
           FWriteBom := cBomInfo[i].HasBOM;
           break;
         end;
       end;

       // Write BOM
       if FWriteBom then
         FStream.WriteBuffer(cBomInfo[i].BOM, cBomInfo[i].Len);



    , то мне несколько поплохело. Как это работает то вообще? Что это за шаманство с использованием i после цикла? Лажа!

    Естественно, полез смотреть более новые версии (3.32). Там этого безобразия уже нет (на while перешли, что логично). Но уж очень код отличается, да и справки я не нашел. А второй раз код просматривать этого NativeXML уже не хочется, чтобы разобраться.

    Поэтому и родилась идея изучить все же TXMLDocument.

    Это лирика была. Показать, что тоже пользуюсь NativeXML и, почему хочу отказаться.

    1.3. Вопрос по NativeXML Кто какой версией пользуется? А нет ли проблем с кодировками при чтении/записи?

    2. TXMLDocument.

    2.1. Ок. понял. Справку копать. Думал, может есть статейка какая-нибудь классическая по теме.
  • iop © (14.06.16 12:27) [6]
    2. TXMLDocument.

    допустим на вход пришел xml документ.
    Известно, что нужное значение лежит в атрибуте "value" узла "unit"
    сам узел лежит на третьем или четвертом этаже вложенности от рута.
    причем их там несколько, а нужен тот, у которого в атрибуте "wanted" записано "1" и нет чайлдов с именем "deleted"

    И используя для разбора такого документа TXMLDocument - программисту очень быстро станет грустно от навигационных методов доступа.

    Это все равно что доставать данные из SQL сервера через TTable
  • DayGaykin © (14.06.16 12:45) [7]

    > iop ©   (14.06.16 12:27) [6]
    >

    Такие задачи бывают редко. Обычно интерес представляет весь документа или его большая часть.
    Мне понравилась потоковая обработка. Xml парсится и сразу "скармливается". Компонент не помню.
  • iop © (14.06.16 13:08) [8]
    Такие задачи бывают редко.

    насколько редки они бывают, чтобы сразу отказываться от xpath в пользу навигации?

    мне например совсем недавно пришлось вынимать данные из xml, которые были сохраненными отчетами FR

    в силу того, что структура заточена на отображение, и совершенно не заточена на "машинное чтение" я бы просто умер бы разбирая такие документы через TXMLDocument

    Потоково - это конечно хорошо и для здоровья не вредно.

    Но вот представь, что сто листов табличного отчета.
    часть данных лежит в строках (самый вложенный дитейл)
    а часть данных только в шапках таблиц.

    Например на 20 странице начинаются данные по дому на улице ленина 1

    и только в шапке 20 страницы есть данные об этом адресе.
    а дальше 10-15 страниц "обезличенных".

    глаза такую превьюшку понимают конечно прекрасно, а машинный импорт - не очень.

    и что бы я сказал в таком случае?
    прастите, такие задачи бывают не часто, поэтому я когжа-то давно решил не владеть xpath и сегодня не могу решить задачу в разумные сроки.
  • iop © (14.06.16 13:16) [9]
    Вот простейший фрагмент для иллюстрации

    таблица с начислениями по лицевым счетам.
    начислений на один лицевой несколько, а сам лицевой только в первой строке.

    REM если лицевой пуст, то берем его из ближайшего предыдущего узла с непустым лицевым

    if c_ls = "" then
     dim node_before : set node_before = ANode.selectsinglenode("(preceding-sibling::b2[4 < string-length(m6/@u)])[last()]")
     if not (node_before is nothing) then
      c_ls   = get_xpath_value(node_before,"./m6/@u")
      c_addr = get_xpath_value(node_before,"./m4/@u")
     end if
    end if



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

    но простейшие примеры - они редкие.
    чаще встречаются более замороченные случаи
  • Тимохов Дима © (14.06.16 13:16) [10]
    У меня задача простая - читать/писать. Без XPath. Т.к. сам использовать не буду, надо подсунуть либу XML под обертку на моем же скриптовом языке. Т.е. нужно для прикладных разработчиков. Там уже есть механизм навигации.

    Столкнулся с тем, что ранний NativeXML (им и пользуюсь), во-первых, как-то мутно работает с кодировками, во-вторых, просто содержит в коде лажу (привел выше). Доверия нет))

    Вот проверенным методам (TXMLDocument) доверие есть. Но надо изучить.

    Например, задался вопросами:
    1. Как сохранять в заданной кодировке - ANSI, UTF-8, 16BE, 16LE и т.д. Пока не нашел.
    2. Понимаю, что XML вроде как case sensitive. Но дабы не нарушать обратную совместимость, мне нужно case INsensitive. Тоже пока не нашел как сделать.
  • iop © (14.06.16 13:18) [11]
    Например, задался вопросами:
    1. Как сохранять в заданной кодировке - ANSI, UTF-8, 16BE, 16LE и т.д. Пока не нашел.
    2. Понимаю, что XML вроде как case sensitive. Но дабы не нарушать обратную совместимость, мне нужно case INsensitive. Тоже пока не нашел как сделать.


    не теми вопросами задаешься.
    кстати на xpath легко и непринужденно делается тот самый case Insensitive

    но мы же не такие.
    мы трудности любим.
  • iop © (14.06.16 13:22) [12]
    Вот проверенным методам (TXMLDocument) доверие есть. Но надо изучить.

    Класс дебильнейший по сути.
    С одной стороны
    "память съем сразу и под весь дом целиком",
    но
    "икспаса не умею, не хочу и не дам"

    успехов тебе в приобретении бесполезных навыков.
  • Тимохов Дима © (14.06.16 14:04) [13]

    > iop ©   (14.06.16 13:22) [12]

    Чот ты агрессивный какой-то))
    Ок, спасибо. Буду думать.
  • sniknik © (14.06.16 14:11) [14]
    > 1. Как сохранять в заданной кодировке - ANSI, UTF-8, 16BE, 16LE и т.д. Пока не нашел.
    IXMLDocument.Encoding:= 'windows-1251'; /utf-8

    > 2. Понимаю, что XML вроде как case sensitive. Но дабы не нарушать обратную совместимость, мне нужно case INsensitive. Тоже пока не нашел как сделать.
    все одно раз делаешь фулскан/пробежку по всем веткам, то и сравнивай не по имени тега, а по UpperCase(имя тега).

    кстати на размер xml-я он очень требовательный... не по детски, буквально 20 мег и обработчик зависает на неопределенное время на элементарных операциях типа Node:= MainNode.ChildNodes['channel'].NextSibling; (попытка взять второй элемент из первого тега "channel" в главной "ветке", да даже просто первый тег "channel" определить, это из разбора "безразмерной ленты RSS", сломалось где-то на размере 30 мегабайт, до этого было тормозно но терпимо по времени)

    вообще xml как формат обмена данными очень переоценен... json не в пример лучше, если конечно все соблюдают правила формирования.
  • Тимохов Дима © (14.06.16 14:30) [15]

    > sniknik ©   (14.06.16 14:11) [14]
    > IXMLDocument.Encoding:= 'windows-1251'; /utf-8

    Да, ты прав. Что-то не углядел пока это свойство.

    Ща бьюсь с тем, что

    Document := TXMLDocument.Create(nil);
    Document.LoadFromFile(FileName);


    не читает ANSI файл, в котором заголовок

    <?xml version="1.0"?>
    <root>...


    т.е. без encoding...
    Выдает:

    An invalid character was found in text content.
    Line: 2
    <.



    Что, без encoding в ANSI вообще не читает?
  • Eraser © (14.06.16 15:42) [16]

    >
    > 1.3. Вопрос по NativeXML Кто какой версией пользуется? А
    > нет ли проблем с кодировками при чтении/записи?

    3.32 - новее по-моему не бывает уже. с кодировками проблем нет.
    в целом, какой может быть ANSI в 2016 году? заем создавать себе проблемы на пустом месте.

    все бы хорошо с NativeXML, беда только в том, что нет кроссплатформенности.


    > Document.LoadFromFile(FileName);

    это вредная функция (по крайней мере, если память меня не подводит, с ней был ряд проблем, но было давно, лет 10 назад), вместо нее следует использовать LoadFromStream с указанием кодировки, проблем не замечал.
  • Rouse_ © (14.06.16 15:47) [17]

    > Eraser ©   (14.06.16 15:42) [16]
    > это вредная функция (по крайней мере, если память меня не
    > подводит, с ней был ряд проблем, но было давно, лет 10 назад),
    >  вместо нее следует использовать LoadFromStream с указанием
    > кодировки, проблем не замечал.

    Похоже с RTF путаешь (стриминговая загрузка чтоб не поломался текст) - с XML вроде ровно было.
  • sniknik © (14.06.16 15:48) [18]
    > не читает ANSI файл, в котором заголовок
    > <?xml version="1.0"?>
    по дефолту кодировка utf-8, определяется при чтении, при пере-присвоении в Encoding другой идет перекодировка.
  • Тимохов Дима © (14.06.16 15:57) [19]

    > Eraser ©   (14.06.16 15:42) [16]
    > в целом, какой может быть ANSI в 2016 году? заем создавать
    > себе проблемы на пустом месте.


    Ты предлагаешь все бросить и заняться портированием на уникод проекта, которым я занимаюсь 20 лет?))) Я когда-то это обязательно сделаю, но не сейчас. У меня и дельфи уже куплены несколько версий. Время не выберу.

    Поэтому ANSI - данность. Третья сторона может присылать, что угодно.
    Вот недавно дали файл без encoding в заголовке, но по факту в UTF-8.


    > 3.32 - новее по-моему не бывает уже. с кодировками проблем нет.


    Может, я чего и не понимаю. Ты пойми, я делаю не для себя, а для разработчиков на скриптовом языке. Мне надо, чтобы работало максимально без проблем в независимости от того, какой файл будет дан в зубы - файлы формирует третья сторона.

    Скармливаю вот такой файл в кодировке ANSI:

    <?xml version="1.0"?>
    <корень атрибут_корня="значение атрибута корня">
    </корень>



    Вот такому коду:

    kNX := TNativeXml.Create(nil);
    kNX.LoadFromFile(FileName);



    Вот ты как будешь получать имена тегов и атрибутов?
    Конкретно для этого файла вызовы

      kNX.Root.NameUnicode
      kNX.Root.AttributeValueByNameWide[sdAnsiToUtf8('атрибут_корня', 1251)]


    Дают пустые строки, а вот вызовы
         
      kNX.Root.Name
      kNX.Root.AttributeValueByName['атрибут_корня']



    При этом, если дать в зубы файл, где

    <?xml version="1.0" encoding="windows-1251"?>



    То работает ровно наоборот - первый набор вызовов дает верные значения, а второй - мусор.

    И вот как с этим работать?
  • Тимохов Дима © (14.06.16 16:01) [20]

    > sniknik ©   (14.06.16 15:48) [18]
    > > не читает ANSI файл, в котором заголовок
    > > <?xml version="1.0"?>
    > по дефолту кодировка utf-8, определяется при чтении, при
    > пере-присвоении в Encoding другой идет перекодировка.

    А ты пойди, прочти вот так:

      kDocument := TXMLDocument.Create(nil);
      kStringStream := TStringStream.Create(
         '<?xml version=\"1.0\"?>'#13+
         '<корень></корень>');
      kDocument.LoadFromStream(kStringStream, xetUnknown);



    Ошибку даст.
    А вот, если <root></root> будет, то все ОК.
  • iop © (14.06.16 16:04) [21]
    Ты пойми, я делаю не для себя, а для разработчиков на скриптовом языке.

    скриптовый тот язык позволяет создавать com?
    если нет, то допили.
    ... и забудь про вымышленные и самомсозданные проблемы с кодировками и прочим на следующие 20 своих лет
  • Тимохов Дима © (14.06.16 16:14) [22]
    Интересный факт.
    Вот это работает и с декларацией, и без, и с кодировкой и без:
    Там, оказывается, два метода есть LoadFromXML перегруженных...

      kDocument := TXMLDocument.Create(nil);
      kDocument.LoadFromXML(DOMString('<?xml version=\"1.0\"?>'#13+'<корень></корень>'));



    Теперь осталось заставить читать из ansi файла без декларации или без encoding...
  • iop © (14.06.16 16:20) [23]
    зачем тебе пролог документа, если тело его содержится в строке?

    пролог с кодировкой актуален для сериализованных документов. фалов например.
  • Тимохов Дима © (14.06.16 16:22) [24]

    > iop ©   (14.06.16 16:20) [23]
    > зачем тебе пролог документа, если тело его содержится в
    > строке?


    Конкретно тут не при чем.

    Мне нужно было: А) прочитать XML из ANSI-строки. Б) прочитать XML из ANSI-файла.

    С п. А справился - есть две функции LoadFromXML - уникодная версия читает русский XML и с прологом и без.

    Вот с п. Б борюсь - если в русском ANSI-файле есть пролог с кодировкой, то все ОК, если кодировки или пробога нет, то не читает с ошибкой.
  • iop © (14.06.16 16:30) [25]
    пример на vbs

    dim xdoc : set xdoc = CreateObject("MSXML2.DOMDocument")

    if xdoc.loadXML("<куку-привет />") then
    MsgBox(xdoc.xml)

    rem dim pi : set pi = xdoc.createProcessingInstruction("xml", "version=""1.0"" encoding=""windows-1251""")
    rem call xdoc.insertBefore(pi,xdoc.documentElement)

    call xdoc.save("test.xml")
    end if


    если выполнить as-is получится utf-8 файл без пролога, но валидный.
    если раскоментить, получится 1251 документ
    если раскоментить и заменить 1251 на утф получится утф с прологом.

    а пока документ в памяти, то данные в нем ни в 1251 ни в утф.

    итого:
    если хочется загрузить из строки и строка эта в среде выполнения "читаема" (русское по-русски) то грузишь просто откусив вообще любой пролог.
    перед сохранением добавляешь нужный пролог или ничего не делаешь и получаешь утф без пролога.
  • Тимохов Дима © (14.06.16 16:52) [26]

    > iop ©   (14.06.16 16:30) [25]

    Во! Напрямую буду брать CreateOleObject и работать. Без обертки.
    Я так и с ADO и c Excel работаю. И тут буду. Благо, должно быть описано хорошо в MSDN.
  • sniknik © (14.06.16 17:31) [27]
    > А ты пойди, прочти вот так:
    а смысл? без указания кодировки как сказал (и во всех доках написано) он принимает utf-8, значит и фактически текст "тела" должен быть в utf-8.

    > А вот, если <root></root> будет, то все ОК.
    без русских букв as is, это и есть utf-8.

    зачем ты специально делаешь неправильно да еще другим говоришь "прочти вот так"? не буду даже пробовать.
  • Юрий Зотов © (14.06.16 17:34) [28]
    Моя эволюция была такой.

    1. DOM. Жрет много памяти.
    2. SAX. Неудобно доставать инфу из глубин XML-дерева.
    3. XPATH. Чтобы прописать пути, надо заранее знать структуру XML.

    То есть, какой использовать - зависит от ситуации. DOM хорош для не слишком больших XML, SAX хорош для неглубоких XML-деревьев, а XPATH хорош, когда известна структура XML.
  • iop © (14.06.16 17:37) [29]
    3. XPATH. Чтобы прописать пути, надо заранее знать структуру XML.


    Ага.
    А чтобы пользовать sql против таблицы надо перед глазами иметь всю таблицу распечатанную в бумаге
  • sniknik © (14.06.16 17:38) [30]
    > kDocument.LoadFromXML(DOMString('<?xml version="1.0"?>'#13+'<корень></корень>'));
    > Теперь осталось заставить читать из ansi файла без декларации или без encoding...
    что сложного в перекодировке?
    kDocument.LoadFromXML(AnsiToUtf8('<?xml version="1.0"?>'#13+'<корень></корень>'));
    или смене "хедера"
    StringList.Strings[0]{<?xml version="1.0"?>}:= '<?xml version="1.0" encoding="windows-1251"?>';
    kDocument.LoadFromXML(StringList.Text);
    ???
  • Тимохов Дима © (14.06.16 18:03) [31]
    Всем спасибо!!!

    Был не прав в своих упорных желаниях сделать не правильно.
    В общем TXMLDocument пользуюсь.
    Свои маленькие локальные задачи решил.

    Случай ANSI без указания encoding считаю ошибочным. Пусть передают правильно.

    XPath пока не нужен. Нужен будет, разберусь.
  • iop © (14.06.16 18:29) [32]
    тут добрая половина слабо представляет о чем говорит.
    но говорит.

    саксу типа не надо знать структуру, но неудобно когда глубоко.
    а xpath не заюзаешь якобы если не знаешь структуры заранее.

    в то время как простейшее выражение "//* | //*/@*" переберет все узлы и все атрибуты документа ничего не зная заранее о структуре дом. точно так же как и сакс

    но структуру якобы надо знать ......
    https://www.youtube.com/watch?v=LcmBp0-fJR8
  • Тимохов Дима © (14.06.16 19:13) [33]

    > iop ©   (14.06.16 18:29) [32]
    > тут добрая половина слабо представляет о чем говорит, но говорит.

    Какой ты смелый))

    ----

    У меня была локальная задача: под свой Facade (https://en.wikipedia.org/wiki/Facade_pattern) подсунуть другую имплементацию. Что я уже и сделал! Мне не нужно напрямую обращаться к XML: нужно открыть, перебрать теги и атрибуты, закрыть. Все.

    Про XPath все понятно - надо будет, разберусь.

    Предлагаю тему закрыть. Ибо исходно она была поднята для выяснение - может есть какой-нибудь известный (но не мне) хрестоматийный материал по использованию TXMLDocument. Оказалось, что надо копать первоисточники. Что надо - раскопал.
  • Тимохов Дима © (21.06.16 20:52) [34]
    Коллеги!

    1. С удивлением узнал, что TXMLDocument умеет получать XML по HTTP.
    Посмотрел исходники, вроде как это делается на уровне MSXML, а не довесок в компоненте TXMLDocument.

    2. Все бы хорошо, но не могу понять, как обрабатывать ошибки. Например,
    при вызове LoadFromFile('http://...'), когда нет соединения, выводится ошибка:
    System error: -2146697211.
    Line: 0



    Долго думал, что может значить -2146697211. Не нашел.

    Может имел кто-то опыт в обработке ошибок обращения по HTTP в компоненте TXMLDocument?

    3. Вообще, каково мнение общественности по работе с HTTP в компоненте TXMLDocument?
    Или лучше через InternetOpen (WinINet) самому в поток читать и его уже скармливать LoadFromStream?

    Спасибо!
  • iop © (21.06.16 20:55) [35]
    так жежь как лучше уже сказали.
  • iop © (21.06.16 20:59) [36]
    С удивлением узнал, что TXMLDocument умеет получать XML по HTTP

    это еще што.....

    прикинь, они выложили коды всех ошибок в инет и твою в том числе

    http://answers.microsoft.com/en-us/windows/forum/all/resolving-run-time-error-runtime-error-2146697211/35bc7487-75fa-419b-9db4-7a1649a85e6b?auth=1
  • Тимохов Дима © (21.06.16 22:13) [37]
    Сам себе отвечу)
    На stackoverflow (http://stackoverflow.com/questions/301546/whats-the-simplest-way-to-call-http-get-url-using-delphi) сильно не советуют пользоваться возможностями TXMLDocument в части получения файла из интернета.
    Мотивация - TXMLDocument дает упрощенный случай (в чем именно, не комментировали). Мне как раз нужно не упрощенный случай - выход в сеть будет из корпоративной сети, т.е. через прокси, коих, как известно, видов не мало.

    Т.к. с WinINet в одном из проектов работал, то переделал на WinINet. Он намного больше позволяет в части обработок ошибок.

    Всем спасибо. Звиняйте, что побеспокоил.


    > op ©   (21.06.16 20:59) [36]

    За код ошибки спасибо.
  • iop © (21.06.16 22:35) [38]
    т.е. через прокси
    Т.к. с WinINet в одном из проектов работал, то переделал на WinINet.

    есть такая категория людей, которые что-то спрашивают,
    но советовать им в ответ ни в коем случае ничего не следует.

    они все равно будут использовать методы, которые требуют ручной поддержки всех типов прокси

    несмотря на то, что
    ixmldomdocument.load('http://......)  сработает без всяких proxyoptions
    если только в системе прокси настроен.

    сам.
  • Тимохов Дима © (21.06.16 22:38) [39]

    > iop ©   (21.06.16 22:35) [38]
    > т.е. через прокси
    > Т.к. с WinINet в одном из проектов работал, то переделал
    > на WinINet.
    >
    > есть такая категория людей, которые что-то спрашивают,

    Тебе скучно что-ли?
Есть новые Нет новых   [134433   +21][b:0][p:0.003]