Работа с объектной моделью документа на примере RSS-ленты.
Цель: вкратце показать как формируется и парситься (разбирается) XML-документ методами DOM.
Часть 1: Создаём.
<?php
// Создаём новый документ.
// Первый параметр конструктора - версия XML, второй - кодировка
$doc_feed = new DOMDocument('1.0', 'UTF-8');
// Любой XML-документ - это дерево узлов. Дерево всегда имеет единственный
// корневой узел - в нашем случае это rss (<rss>…</rss>).
// Создадим элемент с помощью метода createElement
$elem_rss = $doc_feed->createElement('rss');
// Установим для созданного элемента атрибут "version" со значением "2.0"
$elem_rss->setAttribute('version', '2.0');
// Добавим созданый элемент в документ. Т.к. элемент - первый, он становится
// корнем дерева узлов:
$doc_feed->appendChild($elem_rss);
// Создадим элемент channel и добавим его в узел в rss
$elem_channel = $doc_feed->createElement('channel');
$elem_rss->appendChild($elem_channel);
// Далее последовательно создадим и добавим в channel
// узлы title, link, description, language, pubDate (именно в таком виде,
// т.к. XML регистрозависим)
$elem_channel->appendChild( $doc_feed->createElement('title', 'Заголовок RSS-канала') );
$elem_channel->appendChild( $doc_feed->createElement('link', 'http://www.pyha.ru') );
$elem_channel->appendChild( $doc_feed->createElement('description', 'Описание канала') );
$elem_channel->appendChild( $doc_feed->createElement('language', 'ru') );
$elem_channel->appendChild( $doc_feed->createElement('pubDate', date('r')) );
// Теперь добавим в узел channel 3 узла item
for ( $i = 0; $i < 3; ++$i ) {
$elem_item = $doc_feed->createElement('item');
$elem_channel->appendChild($elem_item);
// Создаём для item дочерние элементы
$elem_item->appendChild( $doc_feed->createElement('title', 'Заголок сообщения') );
$elem_item->appendChild( $doc_feed->createElement('link', 'http://www.pyha.ru/somepath') );
$elem_item->appendChild( $doc_feed->createElement('description', 'Описание сообщения') );
}
// Сохраняем документ в файле sample.rss
$doc_feed->save('sample.rss');
?>
В результате получится такой код (только без отступов и знаков переноса)
<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
<channel>
<title>Заголовок RSS-канала</title>
<link>http://www.pyha.ru</link>
<description>Описание канала</description>
<language>ru</language>
<pubDate>Fri, 20 Jul 2007 16:25:59 +0600</pubDate>
<item>
<title>Заголок сообщения</title>
<link>http://www.pyha.ru/somepath</link>
<description>Описание сообщения</description>
</item>
<item>
<title>Заголок сообщения</title>
<link>http://www.pyha.ru/somepath</link>
<description>Описание сообщения</description>
</item>
<item>
<title>Заголок сообщения</title>
<link>http://www.pyha.ru/somepath</link>
<description>Описание сообщения</description>
</item>
</channel>
</rss>
Часть 2: Разбираем
<?php
// Теперь загружаем документ с помощью метода load
$doc_feed = DOMDocument::load('sample.rss');
// Первый дочерний элемент документа - rss,
// первый дочерний элемент rss - channel - т.о. получим элемент channel
$elem_channel = $doc_feed->firstChild->firstChild;
// Получим title (первый дочерний элемент узла channel)
$channel_child = $elem_channel->firstChild;
// Выведем поочередно содержимое дочерних элементов узла channel:
// title, link, description, language и pubDate. Выводить будем пока не встретиться
// элемент, у которого имя тега - item
print "<strong>\n";
while ( $channel_child->tagName != 'item' ) {
print $channel_child->nodeValue . "
\n";
$channel_child = $channel_child->nextSibling;
}
print "</strong>\n";
// Метод getElementsByTagName() применим как к объекту DOMDocument так и к
// DOMElement (как показано далее). В первом случае он вернёт все элементы
// с указанным тегов, во втором - только в рамках указанного узла:
// Получим и пройдёмся по всем узлам item
$list_items = $elem_channel->getElementsByTagName('item');
print "<dl>\n";
foreach ( $list_items as $elem_item ) {
// Элементы, дочерние для item
// первый элемент (firstChild) - title,
// следующий (nextSibling) - link
// последний элемент (lastChild) - description
print "<dt>" . $elem_item->firstChild->nodeValue . "</dt>\n"
. "<dd>" . $elem_item->firstChild->nextSibling->nodeValue
. "
" . $elem_item->lastChild->nodeValue . "</dd>\n";
}
print "</dl>\n";
?>
В результате:
Заголовок RSS-канала
http://www.pyha.ru
Описание канала
ru
Fri, 20 Jul 2007 16:25:59 +0600
Заголок сообщения
http://www.pyha.ru/somepath
Описание сообщения
Заголок сообщения
http://www.pyha.ru/somepath
Описание сообщения
Заголок сообщения
http://www.pyha.ru/somepath
Описание сообщения
Вроде всё. Методов, конечно, гораздо больше, но изучить скорее всего не составит труда.
Ссылки:
- Оффман (eng) на оффсайте
- Введение в DOM (рус.) - советую к прочтению все 6 глав, они небольшие, но в них изложено всё самое необходимое.
- PHP5/XML (рус.) - вкратце обо всех средствах для работы с XML в PHP5
- XML in PHP 5 (eng) - даже перевода не требует - всё и так понятно.
- Спецификация RSS 2.0 (рус.)
зы: пробы