powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Несколько вопросов по парсингу XML
20 сообщений из 20, страница 1 из 1
Несколько вопросов по парсингу XML
    #39919413
Stalker4
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Hi All,

Delphi 10.3.3
Разбор XML делаю с помощью TXMLDocument. Какие то стороние компоненты для этого задействовать бы не хотелось.

Есть такой XM (упрощенной вариант):
Код: xml
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
<?xml version="1.0" encoding="utf-8"?>
<Header standart="1207" version="1.5" >
  <Document idnumber="171" type="0" >
    <RegNumber regdate="2015-09-08">1/16/14-15</RegNumber>
    <Confident flag="0" />
    <DocTransfer type="docx" char_set="UTF-8" description="тестовий.docx" idnumber="914912">текст в base64</DocTransfer>
    <DocTransfer type="pdf" char_set="UTF-8" description="тестовий.pdf" idnumber="914124">текст в base64</DocTransfer>
    <Writer>  
       <Name>Петя</Name>
       <Name>Вася</Name>
  </Writer>
</Header>


Есть xsd файл для валидации этого xml.

1) Поддерживает ли валидация xml через xsd порядок следования нод ?
Например в указанной выше xml сначала идет RegNumber, а потом Confident.
Если я их поменяю местами, то может ли xsd это выявить ?

2) В этой xml есть два нода DocTransfer, но может быть и один.
Как вообще лучше правильно организовать разбор такой xml, в которой могут быть на одном уровне одинаковые имена нод (DocTransfer) и на этом же уровне есть ноды с другими именами (RegNumber,Confident,Writer) ?
Организовать цикл по Document.ChildNodes внутри которого получив очередной нод, смотреть его имя и уже потом вычитывать данные ?
Но тогда может быть много вложенных циклов, скажем в моем примере их будет 2: по Document и по Writer, это усложнит код.
Хотя если порядок следования нод гарантированный, то можно задействовать метод NextSibling (получения следующей ноды текущего уровня).
Или может есть другие варианты ?
Меня смущает именно наличие на одном уровне одинаковые имен нод, вместе с другими именами нод на этом же уровне ...

3) Как с помощью TXMLDocument добавить к XML заголовок вида '<?xml version="1.0" encoding="utf-8"?>' ?
Просто сделать TXMLDocument XML.Insert(0, '') или как то по другому ?
...
Рейтинг: 0 / 0
Несколько вопросов по парсингу XML
    #39919428
zinpub
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Stalker4,

IXMLDOMDocument кажется мне поинтереснее...

читать здесь https://www.amazon.com/Delphi-Developers-Guide-XML-2nd/dp/1591098629
...
Рейтинг: 0 / 0
Несколько вопросов по парсингу XML
    #39919438
Василий 2
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Насколько я знаю, xml не определяет порядок следования узлов.

Касательно одноименных узлов - у тебя получается кашеобразная структура внутри Document за счет гибкости xml. Надо либо обвязывать ее дополнительной прокладкой в коде для представления в удобных структурах Delphi, либо формализовать структуру xml. Например, помещать все узлы DocTransfer в узел-контейнер DocTransfers, даже если DocTransfer всего один. Все зависит от того, насколько ты можешь менять формат xml и какие действия с ним нужны в программе. К примеру, если только читать, то можно и не мудрить со структурой, а в программе работать с классом-посредником. Если же надо и записывать, то чем строже структура xml, тем будет легче и более ошибкоустойчиво
...
Рейтинг: 0 / 0
Несколько вопросов по парсингу XML
    #39919461
Stalker4
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Василий 2
Насколько я знаю, xml не определяет порядок следования узлов.
xml да, не определяет. А xsd ?

Я для интереса, взял эту xml и ее xsd. Сделал валидацию, все OK. Поменял местами RegNumber и Confident, валидация заругалась
Validation of current file using XML schema:
ERROR: Element 'Confident': This element is not expected. Expected is ( RegNumber ).То есть какая то проверке порядка следования нод по xsd все же есть.

Василий 2
Касательно одноименных узлов - у тебя получается кашеобразная структура внутри Document за счет гибкости xml.
Я с Вами согласен, но это не моя xml, ее форма утверждена в законе , поэтому мне остается только приспособиться к ней и работать с тем, что есть.

Мне ее надо и читать (то что мне пришлют) и писать (создание этой xml со своими данными).

Василий 2
а в программе работать с классом-посредником.
Что Вы имеете ввиду под классом-посредником ?
...
Рейтинг: 0 / 0
Несколько вопросов по парсингу XML
    #39919465
Фотография _Vasilisk_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Stalker4
1) Поддерживает ли валидация xml через xsd порядок следования нод ?
Да. Ключевое слово <xsd:sequence>
Stalker4
2) В этой xml есть два нода DocTransfer, но может быть и один.
Код: xml
1.
<xsd:element name="DocTransfer" type="..." maxOccurs="2"/>


Stalker4
Но тогда может быть много вложенных циклов,
Выносите разбор каждого уровня в отдельную процедуру. Тогда все будет читабельно
Stalker4
3) Как с помощью TXMLDocument добавить к XML заголовок вида '<?xml version="1.0" encoding="utf-8"?>' ?
Код: pascal
1.
2.
3.
4.
5.
6.
var
  LNode: IXMLNode;
begin
  LNode := xmlDoc.CreateNode('xml', ntProcessingInstr, 'version="1.0" encoding="utf-8"');
  xmlDoc.ChildNodes.Insert(0, LNode);
end;
...
Рейтинг: 0 / 0
Несколько вопросов по парсингу XML
    #39919469
Фотография _Vasilisk_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
_Vasilisk_
Stalker43) Как с помощью TXMLDocument добавить к XML заголовок вида '<?xml version="1.0" encoding="utf-8"?>' ?
Код: pascal
1.
2.
3.
4.
5.
6.
var
  LNode: IXMLNode;
begin
  LNode := xmlDoc.CreateNode('xml', ntProcessingInstr, 'version="1.0" encoding="utf-8"');
  xmlDoc.ChildNodes.Insert(0, LNode);
end;

А еще лучше
Код: pascal
1.
2.
xmlDoc.Encoding := 'utf-8';
xmlDoc.Version := '1.0';
...
Рейтинг: 0 / 0
Несколько вопросов по парсингу XML
    #39919517
Stalker4
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
_Vasilisk_
Stalker4
1) Поддерживает ли валидация xml через xsd порядок следования нод ?
Да. Ключевое слово <xsd:sequence>[/src]
Есть в xsd такое.

Есть еще такой вопрос.
После разбора этой xml, с ее данными надо произвести определенную объемную работу. Для того, что бы с ними было удобно работать, их желательно сохранить в некие структуры.

Я вижу два варианта:
1) Создается связка record, элементы которых могут быть как простого типа, так и типа других record или типа array of record для множественных элементов.
2) Создается связка классов, простых классов и классов коллекций для множественных элементов.

в.1 проще в написании связки, но сложнее в заполнении ее данными. в.2 - наоборот.

Может есть еще варианты ?

Что лучше выбрать ?
...
Рейтинг: 0 / 0
Несколько вопросов по парсингу XML
    #39919552
Фотография _Vasilisk_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Stalker4
в.1 проще в написании связки, но сложнее в заполнении ее данными. в.2 - наоборот.
Не вижу вообще различий
...
Рейтинг: 0 / 0
Несколько вопросов по парсингу XML
    #39919588
Василий 2
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Stalker4
Что Вы имеете ввиду под классом-посредником ?

Некий класс, который бы прятал детали работы с xml и выставлял наружу, например, DocTransfers: array of DocTransfer и Writers: array of Writer
...
Рейтинг: 0 / 0
Несколько вопросов по парсингу XML
    #39919607
AlexeyM123
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Добавлю свои 5 центов.
Есть такая библиотека https://github.com/benibela/internettools на FreePascal
Сделал REST сервис : на входе XQUERY и XML файл, на выходе JSON.
А уже в Delphi превращать JSON в класс с помощью https://github.com/JensBorrisholt/Delphi-JsonToDelphiClass
Правда, до продакшена еще дело не дошло
...
Рейтинг: 0 / 0
Несколько вопросов по парсингу XML
    #39919767
Stalker4
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
AlexeyM123
А уже в Delphi превращать JSON в класс с помощью https://github.com/JensBorrisholt/Delphi-JsonToDelphiClass
Интересно, а нет ли такого же но для XML, что то типа XMLToDelphiClass ?
...
Рейтинг: 0 / 0
Несколько вопросов по парсингу XML
    #39919771
zinpub
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Stalker4
AlexeyM123
А уже в Delphi превращать JSON в класс с помощью https://github.com/JensBorrisholt/Delphi-JsonToDelphiClass
Интересно, а нет ли такого же но для XML, что то типа XMLToDelphiClass ?


http://docwiki.embarcadero.com/RADStudio/Rio/en/Using_the_XML_Data_Binding_Wizard
...
Рейтинг: 0 / 0
Несколько вопросов по парсингу XML
    #39919881
Stalker4
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
zinpub
Stalker4
пропущено...
Интересно, а нет ли такого же но для XML, что то типа XMLToDelphiClass ?


http://docwiki.embarcadero.com/RADStudio/Rio/en/Using_the_XML_Data_Binding_Wizard
Нет у меня (Delphi 10.3.3. Enterprise) там такого. Можно картинку, где оно находиться ?
...
Рейтинг: 0 / 0
Несколько вопросов по парсингу XML
    #39919890
s62
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Stalker4
Нет у меня (Delphi 10.3.3. Enterprise) там такого. Можно картинку, где оно находиться ?
Нет или не нашел? При открытом проекте:
File -> New -> Other... -> Web -> XML Data Binding
А вообще в индексе справки можно набрать XML Data Binding.
...
Рейтинг: 0 / 0
Несколько вопросов по парсингу XML
    #39921029
Stalker4
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
_Vasilisk_
_Vasilisk_
пропущено...
Код: pascal
1.
2.
3.
4.
5.
6.
var
  LNode: IXMLNode;
begin
  LNode := xmlDoc.CreateNode('xml', ntProcessingInstr, 'version="1.0" encoding="utf-8"');
  xmlDoc.ChildNodes.Insert(0, LNode);
end;

А еще лучше
Код: pascal
1.
2.
xmlDoc.Encoding := 'utf-8';
xmlDoc.Version := '1.0';


Попробовал оба варианта. В обоих случаях есть проблема.
Создал тестовый код:
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
 XMLDocument1.Active := False;
 XMLDocument1.XML.Clear;
 XMLDocument1.Active := True;

 XMLDocument1.Encoding := 'UTF-8';
 XMLDocument1.Version := '1.0';

 XMLDocument1.AddChild('Test').Text := 'test3';

 XMLDocument1.SaveToXML(cXML);
 ShowMessage(cXML);

 XMLDocument1.SaveToFile('3.xml');
 XMLDocument1.XML.SaveToFile('4.xml');



В случае "XMLDocument1.SaveToFile" я получаю XML как и ожидал:
Код: xml
1.
2.
<?xml version="1.0" encoding="UTF-8"?>
<Test>test3</Test>


А в случае "XMLDocument1.SaveToXML" или "XMLDocument1.XML.SaveToFile"
я почему то получаю XML без указания кодировки:
Код: xml
1.
2.
<?xml version="1.0"?>
<Test>test3</Test>


Как это исправить ?
Особенно мне важен метод SaveToXML, так как он возвращает XML в виде строки.
...
Рейтинг: 0 / 0
Несколько вопросов по парсингу XML
    #39921091
Фотография _Vasilisk_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Stalker4
А в случае "XMLDocument1.SaveToXML" или "XMLDocument1.XML.SaveToFile"
я почему то получаю XML без указания кодировки:
Что логично
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
procedure TXMLDocument.SaveToXML(var XML: DOMString);
begin
  CheckActive;
  XML := DOMPersist.xml;
end;

procedure TXMLDocument.SaveToXMLStrings;
var
  XMLData: DOMString;
begin
  if FXMLStrRead <> FModified then
  begin
    SaveToXML(XMLData);
    SetXMLStrings(XMLData);
    FXMLStrRead := FModified;
  end;
end;

function TXMLDocument.GetXML: TStrings;
begin
  { When active, make sure the string list is up to date with what is in the DOM }
  if Active then
    SaveToXMLStrings;
  Result := FXMLStrings;
end;

Т.к. строка сама по себе уже в какой-то кодировке (ANSI/UTF-16) то указывать кодировку в самом XML было бы обманом
Stalker4
Особенно мне важен метод SaveToXML, так как он возвращает XML в виде строки.
А зачем вам XML в виде строки. 99%, что вам нужна не строка, а TStrream
...
Рейтинг: 0 / 0
Несколько вопросов по парсингу XML
    #40036814
Stalker4
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
В большой программе есть такой код

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
 oXMLStream := TStringStream.Create(cXML, TEncoding.UTF8);
 try
   FXMLDocument.Active := False;
   FXMLDocument.XML.LoadFromStream(oXMLStream, TEncoding.UTF8);
   FXMLDocument.Active := True;
 finally
   FreeAndNil(oXMLStream);
 end; 


cXML это переменная типа String в которой находится большой XML (83 мб) загруженный из интернет-сервиса SOAP.

Так вот, на строке FXMLDocument.Active := True я получаю ошибку
Код: plaintext
raised exception class EDOMParseError with message 'Недостаточно памяти для завершения операции.
Хотя в реальности памяти вполне достаточно, по данным TM программа в памяти занимает всего 400 мб.

В ходе попыток победить эту проблему заменил строку
FXMLDocument.XML.LoadFromStream(oXMLStream, TEncoding.UTF8);
на
FXMLDocument.LoadFromStream(oXMLStream, xetUTF_8);

и все отработало нормально.

Вопрос: Не совсем понятно, в чем принципиальное отличие загрузки XML между FXMLDocument.XML.LoadFromStream и FXMLDocument.LoadFromStream ?

И какой вариант все же лучше (правильней) использовать ?
...
Рейтинг: 0 / 0
Несколько вопросов по парсингу XML
    #40036817
Fr0sT-Brutal
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Вообще TEncoding сделан очень тупо и в пике может пожирать что-то около х4 или х5 от исходных данных. Хотя 80 мегов должен прожевать... хз, попробуй трассировку.
А второй метод, скорее всего, кодирует более оптимально.
...
Рейтинг: 0 / 0
Несколько вопросов по парсингу XML
    #40036819
Фотография _Vasilisk_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Предлагаю перестать в произвольные места вставлять TEncoding.UTF8, а прочитать документацию или посмотреть исходники
...
Рейтинг: 0 / 0
Несколько вопросов по парсингу XML
    #40036834
Stalker4
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
_Vasilisk_
Предлагаю перестать в произвольные места вставлять TEncoding.UTF8, а прочитать документацию
Что именно в документации Вы рекомендуете прочитать ? Если можно, то укажите конкретное место.

_Vasilisk_
или посмотреть исходники
Исходники чего именно, методов FXMLDocument.XML.LoadFromStream или FXMLDocument.LoadFromStream или класса TEncoding ?

Так все таки какой метод лучше использовать FXMLDocument.XML.LoadFromStream или FXMLDocument.LoadFromStream ?

Убрал в своем примере FXMLDocument.XML.LoadFromStream параметр TEncoding.UTF8, FXMLDocument смог отпарсить больший кусок XML, но полностью все равно не смог ...

Может это какие то ограничения самого IXMLDocument на размер XML с которым он может работать ?
...
Рейтинг: 0 / 0
20 сообщений из 20, страница 1 из 1
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Несколько вопросов по парсингу XML
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]