Разработчику. Сборник рецептов PHP
Задавайте вопросы

Анализ XML с помощью DOM

Вернуться назад

Задача

Необходимо проанализировать XML-файл с помощью DOM API. Он преобразует файл в дерево, которое можно обработать, применяя функции DOM. DOM позволяет без труда найти и извлечь элементы, удовлетворяющие определенному набору критериев.

Решение

Для этого надо прибегнуть к PHP-расширению DOM XML. Ниже показано, как читать XML из файла:

$dom = domxml_open_file('books.xml');

Теперь приведем пример чтения XML из переменной:

$dom = domxml_open_mem($books);

Можно также извлекать один конкретный узел. Следующее выражение демонстрирует чтение корневого узла:

$root = $dom->document_element();

Приведем пример обработки всех узлов документа с помощью рекурсии типа «сначала вглубь»:

function process_node($node) {
      if ($node->has_child_nodes()) {
            foreach($node->child_nodes() as $n) {
                  process_node($n);
            }
      }
// обработка элементов нижнего уровня
if ($node->node_type() == XML_TEXT_NODE) {
            $content = rtrim($node->node_value());
            if (!empty($content)) {
                  print "$content\n";
            }
      }
}
process_node($root);

Обсуждение

DOM W3C предоставляет независимую от платформы и языка технологию описания структуры и содержимого документа. DOM позволяет прочитать документ XML в дерево узлов, а затем перемещаться по дереву для поиска информации об определенном элементе или группе элементов, удовлетворяющей критерию поиска. Подобный способ называется анализом на основе дерева. В отличие от него, функции XML, не основанные на DOM, позволяют проводить анализ на основе событий.

Кроме того, можно модифицировать структуру документа путем создания, редактирования и удаления узлов. Фактически можно использовать функции DOM XML для создания нового XML-документа (и его элементов) с нуля; см. рецепт (Генерация XML с применением DOM)

Одним из главных преимуществ DOM является то, что, следуя спецификации W3C, функции DOM во многих языках реализуются одинаковым образом. Поэтому работа по переносу логики и инструкций из одного приложения в другое значительно упрощается. Версия PHP 4.3 поставляется с обновленным комплектом функций, более строго согласованным со стандартом DOM, чем в предыдущих версиях PHP. Однако эти функции согласованы еще не на 100%. Будущие версии PHP должны будут обеспечить более точное совмещение. При этом некоторые приложения могут оказаться неработоспособными и потребовать незначительной доработки. Чтобы больше узнать о производимых изменениях, обратитесь к материалам по DOM XML онлайн-версии руководства по PHP по адресу http://www.php.net/domxml. Функции более ранних версий PHP по-прежнему доступны, но их применение очень не одобряется.

Модель DOM большая и сложная. Более подробную информацию ищите в спецификации на http://www.w3.org/DOM/, книге «XML in a Nutshell» и на форумах, посвященных DOM.

Для DOM-анализа в PHP используется модуль libxml, разработанный для проекта Gnome. Загрузить его можно с адреса http://www.xmlsoft.org. Для подключения этого модуля сконфигурируйте PHP с опцией --with-dom.

Функции DOM в PHP объектно-ориентированны. Чтобы перемещаться от узла к узлу, вызывайте такие методы, как $node->child_nodes(), который возвращает дочерние объекты-узлы, и $node->parent_node(), возвращающий объект родительского узла. При обработке узла проверьте его тип и вызовите соответствующий метод:

// $node -это проанализированный с помощью DOM
// узел <book cover="soft">PHP Cookbook</book>
$type = $node->node_type();

switch($type) {
case XML_ELEMENT_NODE:
      // Я – тег. У меня есть свойство «имя тега».
      print $node->node_name(); // печатает свойство имя тега: "book"
      print $nod- >node_value(); // null
      break;
case XML_ATTRIBUTE_NODE:
      // Я – атрибут. У меня есть пара свойств «имя значение».
      print $node->node_name(); // печатает свойство имя: "cover"
      print $node->node_value(); // печатает свойство значение: "soft"
      break;
case XML_TEXT_NODE:
      // Я – часть текста внутри элемента.
      // У меня есть свойства имя и содержание.
      print $node->node_name(); // печатает свойство имя: "#text"
      rint $node->node_value(); // печатает свойство содержание:
                                                      // "PHP Cookbook"

break;
default:
      // другой тип
      break;
}

Для автоматического поиска определенного элемента в дереве DOM используйте функцию get_elements_by_tagname(). Ниже показано, как это сделать в случае нескольких записей book:

<books>
         <book>
                  <title>PHP Cookbook</title>
                  <author>Sklar</author>
                  <author>Trachtenberg</author>
                  <subject>PHP</subject>
         </book>
         <book>
                  <title>Perl Cookbook</title>
                  <author>Christiansen</author>
                  <author>Torkington</author>
                  <subject>Perl</subject>
         </book>
</books>

Следующий фрагмент демонстрирует, как найти всех авторов:

// находим и печатаем всех авторов
$authors = $dom->get_elements_by_tagname('author');

// выполняем цикл по элементам автор
foreach ($authors as $author) {
   // метод child_nodes() извлекает значения элементов автор
 $text_nodes = $author->child_nodes();

foreach ($text_nodes as $text) {
  print $text->node_value();
}
print "\n";
}

Функция get_elements_by_tagname() возвращает массив объектов узлов указанного элемента. Выполняя цикл по каждому потомку элемента, можно извлечь текстовый узел, связанный с этим элементом. Теперь можно получить значения узлов, которыми в данном случае являются имена авторов книг, например Sklar и Trachtenberg.

Вернуться назад

Рейтинг@Mail.ru

Яндекс.Метрика

Индекс цитирования

Рейтинг Сайтов ДОСКИ.РУ