14. XML Library¶
New in version Global: 5.5.0.3950 ms 7
uses
XML;
begin
// Пишите ваш код здесь.
end;
Актуальная версия модуля работает с XML посредством библиотеки LibXml2.dll.
Note
Библиотека libxml2.dll
имеет зависимости от библиотек iconv.dll
и zlib1.dll
.
Note
В целом, работа с кодировкой как входящих, так и исходящих строковых данных, происходит прозрачно. Но полезно будет знать, что весь XML-контент библиотека обрабатывается в кодировке UTF8.
14.1. Краткое руководство¶
Note
Данный API широко использует понятие Node(Узел). К узлам относятся XML-Element-ы, текстовые узлы и коментарии.
14.1.1. Разбор XML¶
Разобрать можно файл *.xml, или строку содержащую XML (CreateXmlDocFromFile
, CreateXmlDocFromString
).
Это первое что следует сделать начав работу с XML - у вас появится экземпляр XML-документа с которым можно работать.
14.1.2. Навигация по документу¶
Этот процесс начинается с получения корневого узла (TbtkXmlDoc.Root
).
Имея узел - можно обратиться к его ближайшим узлам (TbtkXmlNodeCursor.Parent
, TbtkXmlNodeCursor.NextSibling
,
TbtkXmlNodeCursor.PrevSibling
, TbtkXmlNodeCursor.Child
), таким образом реализуется возможность обойти документ.
<pascal>
uses
XML;
function EnumNodes(ANode: TbtkXmlNodeCursor; APrefix: string): string;
begin
Result := '';
while Assigned(ANode) do
begin
Result := Result + APrefix +
ANode.Name + #13 + EnumNodes(ANode.Child, APrefix+' ');
ANode := ANode.NextSibling;
end;
end;
begin
doc := CreateXmlDocFromString('
<root>
<sub1/><sub2/>
<sub3>
<sub31/>
<sub32><sub321/><sub322/><sub323/></sub32>
</sub3>
</root>');
ShowMessage(EnumNodes(doc.Root, ''));
end;
</pascal>
root
text
sub1
sub2
text
sub3
text
sub31
text
sub32
sub321
sub322
sub323
text
text
14.1.3. Копирование узлов¶
Копирование узлов, в том числе между разными документами.
TbtkXmlNodeCursor.AddSibling
TbtkXmlNodeCursor.AddNextSibling
TbtkXmlNodeCursor.AddPrevSibling
TbtkXmlNodeCursor.AddChild
<pascal>
uses
XML;
begin
structure := CreateXmlDocFromString('
<xml>
<emplyer name="ООО Битек">
<unit name="отд. Внедрения"><employee name="Иванов Иван"/></unit>
<unit name="отд. Системный"><employee name="Петров Пётр"/></unit>
<unit name="отд. Продаж"><employee name="Сидоров Сидор"/></unit>
</emplyer>
</xml>');
empList := CreateXmlDocFromString('<xml/>');
staff := structure.CreateXPathContext.FindNodes('//employee');
for i := 0 to staff.Count - 1 do
empList.Root.AddChild(staff.Nodes[i]);
ShowMessage(empList.C14nCanonicalize(False));
end;
</pascal>
<xml><employee name="Иванов Иван"></employee><employee name="Петров Пётр"></employee><employee name="Сидоров Сидор"></employee></xml>
14.1.4. Обращение к атрибутам¶
14.1.5. Поиск узлов¶
Если документ большой, а критерии отбора сложные - перебор узлов может стать непростой задачей - XPath-запросы гарантированно сделают её значительно проще и прозрачнее.
- Для начала работы с XPath потребуется первым делом создать экземпляр
TbtkXPathContext
, он создаётся для каждого отдельного документа(TbtkXmlDoc.CreateXPathContext
) - по которому и будет осуществляться поиск.- Осуществление поиска узлов (
TbtkXPathContext.FindNode
,TbtkXPathContext.FindNodes
).
14.1.6. Канонизация XML¶
В большинстве случаев, исключением будут предельно простые примеры, один и тот же XML-документ может быть представлен множеством разный форм. Разница может быть в порядке расположения атрибутов узлов, порядке описания пространств имён, или способе закрытия гэгов.. И многое-многое другое, вплоть до кодировки в которой сохраняется документ.
Канонизация - это способ избавиться от многообразия форм, приведение документа к его каноническому виду. Такое приведение может быть сделано как для документа целиком, так и для его отдельного узла.
Note
Узел канонического представителя документа не обязательно будет каноничен. Если вам требуется текст канонизированного узла, то нужно проводить канонизацию именно узла!
<pascal>
uses
XML;
begin
doc := CreateXmlDocFromString('
<xml xmlns:ns1="http://namespace.ru/ns1">
<sub1/>
</xml>');
sub1Content := doc.CreateXPathContext.FindNodes('(//.|//@*|//namespace::*)[ancestor-or-self::sub1]');
...
<xml xmlns:ns1="http://namespace.ru/ns1">
<sub1></sub1>
</xml>
<sub1 xmlns:ns1="http://namespace.ru/ns1"></sub1>
14.2. Методы модуля¶
14.2.1. Документ XML¶
-
CreateEmptyXmlDoc
(): TbtkXmlDoc¶ Создать пустой XML-документ.
Return type: TbtkXmlDoc
-
CreateXmlDocFromFile
(FileName: String): TbtkXmlDoc¶ Создать XML-документ, загрузив его из файла.
Warning
Файл должен быть в кодировке UTF8.
Parameters: FileName (String) – путь к XML-файлу Return type: TbtkXmlDoc
-
CreateXmlDocFromString
(Xml: String): TbtkXmlDoc¶ Создать Xml-документ, загрузив его из текста.
Parameters: Xml (String) – текст XML-документа Return type: TbtkXmlDoc
14.3. Классы модуля¶
14.3.1. TbtkXmlDoc¶
-
class
TbtkXmlDoc
¶ Экземпляр XML-документа.
-
CreateXPathContext
(): TbtkXPathContext¶ Создать новый контекст выполнения XPath-запросов. Запросы будут выполняться по узлам данного документа.
Return type: TbtkXPathContext
-
C14nCanonicalize
(Exclusive: Boolean[; Content: TbtkXmlNodeSet; WithComments: Boolean = True]): String¶ Выполнить C14N-канонизацию документа.
Parameters: - Exclusive (Boolean) – Режим выполнения канонизации. В случае
True
- будет использоваться Exclusive алгоритм. - Content (TbtkXmlNodeSet) – Множество узлов подлежищих канонизации. Ниодин узел не включённый в этот набор не попадёт в итоговый XML.
- WithComments (Boolean) – Флаг указывает включать ли коментарии в итоговый XML.
Return type: String
See also
- Exclusive (Boolean) – Режим выполнения канонизации. В случае
-
SetRootNode
(NewRoot: TbtkXmlNodeCursor[; Recursive: Boolean = True])¶ Устанавливает копию узла корневым узлом документа.
Parameters: - NewRoot (TbtkXmlNodeCursor) – Узел по образу которого будет создан новый корневой узел документа.
- Recursive (Boolean) –
True
- Копирование узла NewNode будет полным(рекурсивным), иначе - вложенные узлы копироваться не будут.
-
Root
(): TbtkXmlNodeCursor¶ Корневой узел документа
Return type: TbtkXmlNodeCursor
-
ToString
(): String¶ XML описывающий данный документ.
Return type: String <pascal> uses XML; begin doc := CreateXmlDocFromString(' <root xmlns:ns1="http://exaple.ru/scheme#test" > <sub1></sub1><sub2/> <sub3 id = "foo"> <sub31/> <sub32><ns1:sub321/><sub322/><sub323/></sub32> </sub3> </root>'); ShowMessage(doc.ToString); end; </pascal>
<?xml version="1.0"?> <root xmlns:ns1="http://exaple.ru/scheme#test"> <sub1/><sub2/> <sub3 id="foo"> <sub31/> <sub32><ns1:sub321/><sub322/><sub323/></sub32> </sub3> </root>
-
14.3.2. TbtkXPathContext¶
-
class
TbtkXPathContext
¶ Объект выполнения XPath-запросов. Подробнее о XPath можно прочесть на W3C. Также полезным будет прочесть XPath Tutorial.
В существующей версии данного модуля: XPath предлагается эксплуатировать как поисковую машину - искать интересующие узлы XML-документа не перебором от
Root-а
, а таргетированно, лаконичным запросом.-
FindNode
(XPath: String[; NullAllowed: Boolean = False]): TbtkXmlNodeCursor¶ Метод предназначен для выполнения запроса на поиск единственного узла.
Parameters: - XPath (String) – Текст XPath-запроса.
- NullAllowed (Boolean) –
Флаг говорит что запрос не обязательно вернёт узел. При выставленном флаге, если запрос не вернул ни одного узла:
- метод не станет возбуждать исключение.
- метод вернёт
nil
.
Return type: Raises: - EbtkXPathError – XPath-запрос не на получение узлов
- EbtkXPathError – XPath-запрос вернул больше одного узла
- EbtkXPathError – XPath-запрос не соотвутствует ниодному узлу (при
NullAllowed=False
)
-
FindNodes
(XPath: String): TbtkXmlNodeSet¶ Метод предназначен для выполнения запроса на поиск узлов.
Parameters: XPath (String) – Текст XPath-запроса. Return type: TbtkXmlNodeSet Raises: EbtkXPathError – XPath-запрос не на получение узлов
-
AddVariable
(Name: String; Value: TbtkXmlNodeSet)¶ Определить переменную доступную в последующих XPath-запросах.
Parameters: - Name (String) – Наименование переменной
- Value (TbtkXmlNodeSet) – Множество узлов представленное данной переменной в запросах
-
AddNamespace
(Prefix, Ref: String)¶ Определить пространство имён доступное в последующих XPath-запросах. Можно будет искать узлы описанные в схеме данных данного пространства имён.
Parameters: - Prefix (String) – Префикс простанства имён который можно будет использовать в последующих запросах.
- Ref (String) – Ссылка на схему данных определяющую указанное пространство имён.
xpath.AddNamespace('xades', 'http://uri.etsi.org/01903/v1.3.2#'); xpath.FindNode('//xades:Cert[1]');
-
14.3.3. TbtkXmlNodeCursor¶
-
class
TbtkXmlNodeCursor
¶ Узел XML-документа.
-
Name
: String¶ Имя узла (тэга).
Return type: String doc := CreateDocFromString('<xml></xml>'); if doc.Root.Name = 'xml' then ShowMessage('Всё верно.');
-
Attributes
: String¶ Индексное свойство. Получить/задать значение атрибута XML-узла. Индексное свойство - в квадратных скобках указывается наименование интересующего атрибута строкой.
Parameters: Name (String) – Наименование атрибута узла Return type: String <pascal> uses XML; begin doc := CreateXmlDocFromString('<root existing="test"/>'); doc.Root.Attributes['newOne'] := 'new ' + doc.Root.Attributes['existing']; ShowMessage(doc.ToString); end; </pascal>
<?xml version="1.0"?> <root existing="test" newOne="new test"/>
-
OuterText
: String¶ Получить XML-текст данного узла (со всеми подузлами и атрибутами).
Return type: String
-
Text
: String¶ Получить/задать текст содержащийся в данном узле (со всеми подузлами). Результат - сумма всех текстовых подузлов данного узла.
Return type: String ShowMessage(node.Text); node.Text := 'new text. nested nodes are droped';
-
NextSibling
: TbtkXmlNodeCursor¶ Узел следующий за данным. Если такового нет -
nil
.Return type: TbtkXmlNodeCursor: TbtkXmlNodeCursor
-
PrevSibling
: TbtkXmlNodeCursor¶ Узел предшествующий данному. Если такового нет -
nil
.Return type: TbtkXmlNodeCursor
-
Child
: TbtkXmlNodeCursor¶ Первый вложенный узел. Если такового нет -
nil
.Return type: TbtkXmlNodeCursor
-
Parent
: TbtkXmlNodeCursor¶ Родительский узел. Или
nil
, если его нет.Return type: TbtkXmlNodeCursor
-
AddSibling
(Node: TbtkXmlNodeCursor[; Recusive: Boolean = True]): TbtkXmlNodeCursor¶ Копия переданного узла будет добавлена в тот же список узлов что и данный.
Parameters: - Node (TbtkXmlNodeCursor) – Узел копия которого будет добавлена.
- Recusive (Boolean) – Режим копирования переданного узла.
Returns: Интегрированная в структуру документа копия узла
Node
.Return type:
-
AddNextSibling
(Node: TbtkXmlNodeCursor[; Recusive: Boolean = True]): TbtkXmlNodeCursor¶ Копия переданного узла будет добавлена следующим узлом по отношению к данному.
Parameters: - Node (TbtkXmlNodeCursor) – Узел копия которого будет добавлена.
- Recusive (Boolean) – Режим копирования переданного узла.
Returns: Интегрированная в структуру документа копия узла
Node
.Return type:
-
AddPrevSibling
(Node: TbtkXmlNodeCursor[; Recusive: Boolean = True]): TbtkXmlNodeCursor¶ Копия переданного узла будет добавлена как предыдущий узел по отношению к данному.
Parameters: - Node (TbtkXmlNodeCursor) – Узел копия которого будет добавлена.
- Recusive (Boolean) – Режим копирования переданного узла.
Returns: Интегрированная в структуру документа копия узла
Node
.Return type:
-
AddChild
(Node: TbtkXmlNodeCursor[; Recusive: Boolean = True]): TbtkXmlNodeCursor¶ Копия переданного узла будет добавлена в конец списка вложенных узлов.
Parameters: - Node (TbtkXmlNodeCursor) – Узел копия которого будет добавлена.
- Recusive (Boolean) – Режим копирования переданного узла.
Returns: Интегрированная в структуру документа копия узла
Node
.Return type:
-
14.3.4. TbtkXmlNodeSet¶
-
class
TbtkXmlNodeSet
¶ Набор узлов. Как правило это результат выполнения поискового
XPath-запроса
.-
Count
: Integer¶ Количество узлов в данном наборе.
Return type: Integer
-
Nodes
: TbtkXmlNodeCursor¶ Индексное свойство. Возвращает i-тый узел в наборе.
Parameters: Index (Integer) – индекс узла в наборе Return type: TbtkXmlNodeCursor Raises: EbtkXPathOutOfIndex – Index вне диапазона допустимых значений ( 0 >= Index > Count
)
-