Skip to content

Commit a16e529

Browse files
committed
Integrated "/application_structure/helper_classes/xml_document_handling.rst"
1 parent 95d7302 commit a16e529

File tree

1 file changed

+211
-2
lines changed

1 file changed

+211
-2
lines changed
Lines changed: 211 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,216 @@
11
Обработка XML документов
22
========================
3-
`Data Source`_
3+
`Data Source`_ `Eng Data Source`_
44

5-
...
5+
``XML`` - удобный формат описания данных, который строится по древовидной структуре. Каждый элемент может содержать
6+
значение и/или другие элементы. Текст внутри элемента может чередоваться с дочерними элементами, но он всё равно будет
7+
расценен как единое значение. Кроме того, у каждого элемента могут быть заданы атрибуты. Всё выше описанное отражено в
8+
ниже приведённом примере (пусть это будет файл ``sample.xml``):
9+
10+
.. code:: xml
11+
12+
<?xml version="1.0" encoding="utf-8"?>
13+
<our_document>
14+
<some_tag>
15+
Some tag's content.
16+
</some_tag>
17+
<planet_earth>
18+
<continent id="1">
19+
North America
20+
<country id="1">
21+
Canada
22+
</country>
23+
<country id="2">
24+
USA
25+
</country>
26+
</continent>
27+
<continent id="2">
28+
Europe
29+
<country id="1">
30+
Estonia
31+
</country>
32+
<country id="2">
33+
Latvia
34+
</country>
35+
<country id="3">
36+
Lithuania
37+
</country>
38+
</continent>
39+
</planet_earth>
40+
</our_document>
41+
42+
.. _блок_cdata:
43+
44+
Блок CDATA
45+
----------
46+
47+
Если требуется указать в качестве содержания одного из элементов символы, которые могут помешать корректной разборке
48+
XML документа, то нужно содержание элемента заключать в блок CDATA. К ряду символов таких символов относятся символы
49+
``>``, ``<`` и ``&``. Синтаксис блока ``CDATA`` выглядит следующим образом:
50+
51+
.. code:: xml
52+
53+
<![CDATA[Some symbolic data, that > breaks & xml]]>
54+
55+
Данные внутри блока ``CDATA`` не должны содержать последовательность ``]]>``, т.к. она будет воспринята как окончание
56+
данного блока. Если задание такой последовательности символов необходимо, следует воспользоваться следующим подходом:
57+
58+
.. code:: xml
59+
60+
<![CDATA[]]]]><![CDATA[>]]>
61+
62+
В выше приведённом примере данные разбиты на два фрагмента и каждый из них заключён в свой блок ``CDATA``. Особенно
63+
удобно применение ``CDATA`` в случае, когда нужно написать ``XML``, который будет показан пользователю, но не обработан
64+
при разборке XML документа.
65+
66+
Получение XML документа
67+
-----------------------
68+
69+
Перед тем, как разбирать ``XML`` документ, содержащийся в файле, его нужно сначала прочитать.
70+
71+
Получение локального файла
72+
^^^^^^^^^^^^^^^^^^^^^^^^^^
73+
74+
Для получения локального файла (т.е. находящегося на том-же компьютере, что и сам сайт) следует использовать
75+
стандартную функцию `file_get_contents <https://www.php.net/file_get_contents>`__.
76+
Данная функция возвращает содержание файла, путь к которому передан в качестве первого её аргумента.
77+
78+
.. code:: php
79+
80+
$file_contents = file_get_contents(WRITEABLE . '/user_files/sample.xml');
81+
82+
Получение удалённого файла
83+
^^^^^^^^^^^^^^^^^^^^^^^^^^
84+
85+
Функция `file_get_contents <https://www.php.net/file_get_contents>`__ также позволяет
86+
получать содержимое файлов, находящихся на удалённых ресурсах. Однако, в целях безопасности, на сервере может быть
87+
запрещена эта возможность. Поэтому настоятельно рекомендуется получать удалённый файл при помощи стандартного класса
88+
K4 - ``kCurlHelper``.
89+
90+
.. code:: php
91+
92+
$curl_helper =& $this->Application->recallObject('CurlHelper');
93+
/* @var $curl_helper kCurlHelper */
94+
95+
$xml_data = $curl_helper->Send('http://sample-host.com/sample.xml');
96+
97+
У метода ``Send`` также есть второй необязательный параметр, который указывает на то, что нужно закрывать соединение
98+
сразу после получения содержания документа. По умолчанию он равен ``true``, т.е. закрывать соединение.
99+
100+
Разборка XML документа
101+
----------------------
102+
103+
В классе ``kXMLHelper`` реализован удобный механизм разбора XML документа. Сначала следует создать экземпляр класса.
104+
105+
.. code:: php
106+
107+
$xml_helper =& $this->Application->recallObject('kXMLHelper');
108+
/* @var $xml_helper kXMLHelper */
109+
110+
Далее, начать обработку полученного ранее XML документа.
111+
112+
.. code:: php
113+
114+
$root_node =& $xml_helper->Parse($file_contents);
115+
116+
В результате будет возвращена древовидная структура объектов, в которой все объекты связаны при помощи ссылок.
117+
Содержимое каждого объекта класса ``kXMLNode`` выглядит так:
118+
119+
.. code:: php
120+
121+
kxmlnode Object (
122+
[Name] => xml_element_name
123+
[Attributes] => Array
124+
(
125+
[1st_attribute_name] => 1st_attribute_value
126+
[2nd_attribute_name] => 2nd_attribute_value
127+
...
128+
)
129+
[Children] => Array
130+
(
131+
[0] => kxmlnode Object
132+
[1] => kxmlnode Object
133+
...
134+
)
135+
[Data] => text_value_that_this_XML_element_encapsulates
136+
[firstChild] => kxmlnode Object
137+
[lastChild] => kxmlnode Object
138+
[Parent] => kxmlnode Object
139+
[Position] => 1
140+
)
141+
142+
.. note::
143+
144+
Всё ниже приведённое описание содержания объекта класса kXMLNode будет основано на примере, приведённом в
145+
начале статьи.
146+
147+
Переменной ``$root_node`` будет присвоен родительский (root) объект, т.е. это объект xml-элемента ``our_document``.
148+
Атрибут ``Children`` (private) содержит массив всех дочерних элементов текущего элемента. В данном примере ими
149+
являются два элемента - ``some_tag`` и ``planet_earth``. У последнего - два дочерних элемента ``continent``. Важно
150+
понимать, что элементы массива - точно такие же объекты, как и текущий. У них, в свою очередь, могут быть свои дочерние
151+
элементы, и так далее.
152+
153+
У каждого элемента есть атрибут ``Position``. Это - порядковый номер элемента среди соседних элементов (элементов того
154+
же уровня, например - "country" Canada и "country" USA). Атрибуты ``firstChild`` и ``lastChild`` содержат первый и
155+
последний (с точки зрения его ``Position``) дочерний элемент соответственно.
156+
157+
Для последующей обработки полученной информации используется методы и атрибуты именно класса ``kXMLNode``.
158+
159+
Практическое использование kXMLHelper
160+
-------------------------------------
161+
162+
Ниже приведён код, который распечатает все страны описанного выше XML-документа.
163+
164+
.. code:: php
165+
166+
$root_node =& $xml_helper->Parse($xml_data);
167+
/* @var $root_node kXMLNode */
168+
169+
// Getting first continent node
170+
$continent_node =& $root_node->FindChild('continent');
171+
172+
// Cycling through it and all the rest continent nodes
173+
do {
174+
// Getting first country node
175+
$country_node =& $continent_node->firstChild;
176+
177+
// Cycling through it and all the rest continent nodes
178+
do {
179+
echo $continent_node->Attributes['ID'] . ' - ' . trim($continent_node->Data) . ': ' . $country_node->Attributes['ID'] . ' - ' . trim($country_node->Data) . '<br/>';
180+
} while ($country_node =& $country_node->NextSibling());
181+
} while ($continent_node =& $continent_node->NextSibling());
182+
183+
В переменной ``$continent_node`` сохраняется первый найденный объект ``continent``, т.е. - ``North America``. В
184+
первом цикле перебираются континенты. Для перехода к элементу того же уровня используется метод ``NextSibling``
185+
(есть противоположный ему метод ``PrevSibling``). Из континента выбирается первая страна. Внутренний цикл перебирает
186+
все страны данного континента и делает вывод в приведённом ниже формате. Как можно заметить, текстовое значение
187+
элементов доступно через атрибут ``Data``.
188+
189+
- ``1 - North America: 1 - Canada``
190+
- ``1 - North America: 2 - USA``
191+
- ``2 - Europe: 1 - Estonia``
192+
- ``2 - Europe: 2 - Latvia``
193+
- ``2 - Europe: 3 - Lithuania``
194+
195+
Методы класса "kXMLNode"
196+
------------------------
197+
198+
Ниже приведены public методы класса ``kXMLNode``. Все методы рассчитаны на чтение данных, но не на их запись.
199+
200+
+---------------------------------------+------------------------------------------------------------------------------+
201+
| метод | описание |
202+
+=======================================+==============================================================================+
203+
| ``&FindChild($name)`` | Возвращает первый встретившийся элемент-потомок с указанным именем. Работает |
204+
| | рекурсивно, до самого последнего уровня. |
205+
+---------------------------------------+------------------------------------------------------------------------------+
206+
| ``FindChildValue($name, $attr=null)`` | Возвращает либо значение элемента-потомка (если задано только его имя), либо |
207+
| | один из атрибутов (если явно указан). |
208+
+---------------------------------------+------------------------------------------------------------------------------+
209+
| ``&GetChildByPosition($position)`` | Возвращает дочерний элемент, который находится по указанной позиции. |
210+
+---------------------------------------+------------------------------------------------------------------------------+
211+
| ``GetXML()`` | Генерирует и возвращает XML-документ, построенный от текущего элемента. |
212+
| | Актуально при предыдущем изменении структуры и не только. |
213+
+---------------------------------------+------------------------------------------------------------------------------+
6214

7215
.. _Data Source: http://guide.in-portal.org/rus/index.php/K4:%D0%9E%D0%B1%D1%80%D0%B0%D0%B1%D0%BE%D1%82%D0%BA%D0%B0_XML_%D0%B4%D0%BE%D0%BA%D1%83%D0%BC%D0%B5%D0%BD%D1%82%D0%BE%D0%B2
216+
.. _Eng Data Source: http://guide.in-portal.org/eng/index.php/K4:KXMLHelper

0 commit comments

Comments
 (0)