K4:Обработка XML документов
From In-Portal Developers Guide
| ||
---|---|---|
Статьи в этой категории | ||
|
XML
- удобный формат описания данных, который строится по древовидной структуре. Каждый элемент может содержать значение и/или другие элементы. Текст внутри элемента может чередоваться с дочерними элементами, но он всё равно будет расценен как единое значение. Кроме того, у каждого элемента могут быть заданы атрибуты. Всё выше описанное отражено в ниже приведённом примере (пусть это будет файл "sample.xml
"):
<?xml version="1.0" encoding="utf-8"?> <our_document> <some_tag> Some tag's content. </some_tag> <planet_earth> <continent id="1"> North America <country id="1"> Canada </country> <country id="2"> USA </country> </continent> <continent id="2"> Europe <country id="1"> Estonia </country> <country id="2"> Latvia </country> <country id="3"> Lithuania </country> </continent> </planet_earth> </our_document>
Contents |
Блок CDATA
Если требуется указать в качестве содержания одного из элементов символы, которые могут помешать корректной разборке XML документа, то нужно содержание элемента заключать в блок CDATA. К ряду символов таких символов относятся символы ">
", "<
" и "&
". Синтаксис блока CDATA
выглядит следующим образом:
<![CDATA[Some symbolic data, that > breaks & xml]]>
Данные внутри блока CDATA
не должны содержать последовательность "]]>
", т.к. она будет воспринята как окончание данного блока. Если задание такой последовательности символов необходимо, следует воспользоваться следующим подходом:
<![CDATA[]]]]><![CDATA[>]]>
В выше приведённом примере данные разбиты на два фрагмента и каждый из них заключён в свой блок CDATA
. Особенно удобно применение CDATA
в случае, когда нужно написать XML
, который будет показан пользователю, но не обработан при разборке XML документа.
Получение XML документа
Перед тем, как разбирать XML
документ, содержащийся в файле, его нужно сначала прочитать.
Получение локального файла
Для получения локального файла (т.е. находящегося на том-же компьютере, что и сам сайт) следует использовать стандартную функцию file_get_contents. Данная функция возвращает содержание файла, путь к которому передан в качестве первого её аргумента.
$file_contents = file_get_contents(WRITEABLE . '/user_files/sample.xml');
Получение удалённого файла
Функция file_get_contents также позволяет получать содержимое файлов, находящихся на удалённых ресурсах. Однако, в целях безопасности, на сервере может быть запрещена эта возможность. Поэтому настоятельно рекомендуется получать удалённый файл при помощи стандартного класса K4 - kCurlHelper
.
$curl_helper =& $this->Application->recallObject('CurlHelper'); /* @var $curl_helper kCurlHelper */ $xml_data = $curl_helper->Send('http://sample-host.com/sample.xml');
У метода Send
также есть второй необязательный параметр, который указывает на то, что нужно закрывать соединение сразу после получения содержания документа. По умолчанию он равен "true
", т.е. закрывать соединение.
Разборка XML документа
В классе kXMLHelper
реализован удобный механизм разбора XML документа. Сначала следует создать экземпляр класса.
$xml_helper =& $this->Application->recallObject('kXMLHelper'); /* @var $xml_helper kXMLHelper */
Далее, начать обработку полученного ранее XML документа.
$root_node =& $xml_helper->Parse($file_contents);
В результате будет возвращена древовидная структура объектов, в которой все объекты связаны при помощи ссылок. Содержимое каждого объекта класса kXMLNode
выглядит так:
kxmlnode Object ( [Name] => xml_element_name [Attributes] => Array ( [1st_attribute_name] => 1st_attribute_value [2nd_attribute_name] => 2nd_attribute_value ... ) [Children] => Array ( [0] => kxmlnode Object [1] => kxmlnode Object ... ) [Data] => text_value_that_this_XML_element_encapsulates [firstChild] => kxmlnode Object [lastChild] => kxmlnode Object [Parent] => kxmlnode Object [Position] => 1 )
Всё ниже приведённое описание содержания объекта класса kXMLNode будет основано на примере, приведённом в начале статьи. |
Переменной $root_node
будет присвоен родительский (root) объект, т.е. это объект xml-элемента "our_document
". Атрибут "Children
" (private) содержит массив всех дочерних элементов текущего элемента. В данном примере ими являются два элемента - "some_tag
" и "planet_earth
". У последнего - два дочерних элемента "continent
". Важно понимать, что элементы массива - точно такие же объекты, как и текущий. У них, в свою очередь, могут быть свои дочерние элементы, и так далее.
У каждого элемента есть атрибут Position
. Это - порядковый номер элемента среди соседних элементов (элементов того же уровня, например - "country" Canada и "country" USA). Атрибуты "firstChild
" и "lastChild
" содержат первый и последний (с точки зрения его Position
) дочерний элемент соответственно.
Для последующей обработки полученной информации используется методы и атрибуты именно класса kXMLNode
.
Практическое использование kXMLHelper
Ниже приведён код, который распечатает все страны описанного выше XML-документа.
$root_node =& $xml_helper->Parse($xml_data); /* @var $root_node kXMLNode */ // Getting first continent node $continent_node =& $root_node->FindChild('continent'); // Cycling through it and all the rest continent nodes do { // Getting first country node $country_node =& $continent_node->firstChild; // Cycling through it and all the rest continent nodes do { echo $continent_node->Attributes['ID'] . ' - ' . trim($continent_node->Data) . ': ' . $country_node->Attributes['ID'] . ' - ' . trim($country_node->Data) . '<br/>'; } while ($country_node =& $country_node->NextSibling()); } while ($continent_node =& $continent_node->NextSibling());
В переменной $continent_node
сохраняется первый найденный объект "continent
", т.е. - "North America
". В первом цикле перебираются континенты. Для перехода к элементу того же уровня используется метод NextSibling
(есть противоположный ему метод PrevSibling
). Из континента выбирается первая страна. Внутренний цикл перебирает все страны данного континента и делает вывод в приведённом ниже формате. Как можно заметить, текстовое значение элементов доступно через атрибут "Data
".
1 - North America: 1 - Canada 1 - North America: 2 - USA 2 - Europe: 1 - Estonia 2 - Europe: 2 - Latvia 2 - Europe: 3 - Lithuania
Методы класса "kXMLNode"
Ниже приведены public методы класса kXMLNode
. Все методы рассчитаны на чтение данных, но не на их запись.
метод | описание |
---|---|
&FindChild($name)
| Возвращает первый встретившийся элемент-потомок с указанным именем. Работает рекурсивно, до самого последнего уровня. |
FindChildValue($name, $attr=null)
| Возвращает либо значение элемента-потомка (если задано только его имя), либо один из атрибутов (если явно указан). |
&GetChildByPosition($position)
| Возвращает дочерний элемент, который находится по указанной позиции. |
GetXML()
| Генерирует и возвращает XML-документ, построенный от текущего элемента. Актуально при предыдущем изменении структуры и не только. |