ФорумПрограммированиеПыхнуть хотите?F.A.Q. → DOM. Быстрое знакомство

DOM. Быстрое знакомство

  • Timur

    Сообщения: 1068 Репутация: N Группа: Джедаи

    Spritz 20 июля 2007 г. 4:30

    [size=14pt]Быстрое знакомство с DOM[/size]

    Работа с объектной моделью документа на примере 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
    Описание сообщения


    Вроде всё. Методов, конечно, гораздо больше, но изучить скорее всего не составит труда.

    Ссылки:


    зы: пробы пера клавиатуры :)
  • adw0rd

    Сообщения: 22902 Репутация: N Группа: в ухо

    Spritz 18 августа 2007 г. 12:37, спустя 29 дней 8 часов 7 минут

    +1

    Всегда хотел затронуть эту тему (для изучения), но как всегда нехватало времени… Спасибо Тимуру!

    Даже добавил в ссылки http://ru.wikipedia.org/wiki/DOM
    adw/0
  • sap

    Сообщения: ? Репутация: N Группа: Кто попало

    Spritz 27 мая 2008 г. 5:49, спустя 282 дня 17 часов 11 минут

    Из-за чего возникает ошибка
    Warning: DOMDocument::createElement() [function.DOMDocument-createElement]: unterminated entity reference in=view&id=295 in … on line 37

    Строка 37:
    $elem_item->appendChild( $doc_feed->createElement('link', 'http://exmaple.com/index.php?go=News&in=view&id='.$row['id']) );

    Я так догадываюсь, из-за амперсанда? Как исправить?
  • md5

    Сообщения: 11951 Репутация: N Группа: в ухо

    Spritz 27 мая 2008 г. 5:53, спустя 4 минуты 18 секунд

    &?
    написанож
    entity reference
    все умрут, а я изумруд
  • sap

    Сообщения: ? Репутация: N Группа: Кто попало

    Spritz 27 мая 2008 г. 5:56, спустя 2 минуты 57 секунд

    Я туплю =\
  • beerman

    Сообщения: ? Репутация: N Группа: Кто попало

    Spritz 17 сентября 2008 г. 17:23, спустя 113 дней 11 часов 27 минут

    $elem_item->appendChild( $doc_feed->createElement('link', 'http://exmaple.com/index.php?go=News&in=view&id='.$row['id']) );

    подскажите, плз, как в этом случае установить setAttribute?
  • Timur

    Сообщения: 1068 Репутация: N Группа: Джедаи

    Spritz 18 сентября 2008 г. 2:36, спустя 9 часов 13 минут 26 секунд

    в каком этом случае?
    $elem_link = $doc_feed->createElement('link', 'http://exmaple.com/index.php?go=News&in=view&id='.$row['id']);
    $elem_link->setAttribute('name', 'value');
    $elem_item->appendChild($elem_link);
  • phpdude

    Сообщения: 26617 Репутация: N Группа: в ухо

    Spritz 22 ноября 2008 г. 12:53, спустя 65 дней 11 часов 16 минут

    забудьте прошлое! живите настоящим!

    http://ru2.php.net/simplexml_load_string

    рулез. дом-УГ.
    Сапожник без сапог

Пожалуйста, авторизуйтесь, чтобы написать комментарий!