The OpenNET Project / Index page

[ новости /+++ | форум | теги | ]

Альтернатива DOM XML на PHP (PHP4) (xml php)


<< Предыдущая ИНДЕКС Поиск в статьях src Установить закладку Перейти на закладку Следующая >>
Ключевые слова: xml, php,  (найти похожие документы)
From: Александр Неткачев <alex at devlink.crimea.ua> Newsgroups: Date: Mon, 19 Apr 2004 14:31:37 +0000 (UTC) Subject: Альтернатива DOM XML на PHP (PHP4) Оригинал статьи находится на http://devlink.crimea.ua Для читателей ------------- Материал этой статьи в первую очередь пригодится тем, кто ищет альтернативу XML DOM расширению PHP и использует PHP 4. Начинающие изучать XML или использующие XML программисты на PHP могут также почерпнуть для себя множество полезного из материала этой статьи. Предыстория ----------- Изучив DOM XML расширение в PHP 4, я столкнулся с некоторыми трудностями в его применении. Во-первых, это его статус экспериментального, в результате чего некоторые провайдеры это расширение отключают. Во-вторых, некоторое несоответствие в именовании методов и свойств с W3C DOM Specification (href="http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226) В-третьих, в PHP 5 расширение изменили с целью большего совпадения с W3C DOM спецификацией, что автоматически делает его более привлекательным объектом для изучения. Но желание применить DOM для работы с XML документами было очень большим. Кстати, DOM также предполагалось использовать как основу для планируемой темплейтной библиотеки. Это привело к тому, что сформировалось решение написать собственную простую реализацию DOM XML на PHP 4, которая содержит только функции, необходимые для обхода XML дерева и для простых его модификаций. Но то, что реализовано, должно быть как можно более приближено к W3C Document Object Model (DOM) Level 3 Core Specification (http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226) Потенциал подобной реализации DOM достаточно велик, поскольку до PHP 5 еще остается время, а использовать и обрабатывать XML тем или иным образом приходится достаточно часто. Основа XML Document Object Model -------------------------------- Все варианты организации XML дерева основаны следующих правилах: a) узел дерева связан с несколькими потомками и б) два узла не могут быть связанны с одним и тем же потомком. Для задания потомков узла можно использовать список или массив динамической длины. Данные узла и указатели на потомков можно хранить в структуре, классе или массиве. Дополнительно, узел дерева может содержать информацию о предке, двух соседних узлах и корне. Спецификация DOM не определяет внутренний способ хранения элементов, но задает методы обращения к ним, предполагая, что язык реализации поддерживает ООП. Основой W3C XML DOM является интерфейс Node, который и представляет собой узел дерева и создается почти для всех составляющих XML документа, в том числе для его тегов, атрибутов, текста, CDATA, комментариев и других. Основные его элементы следующие: // некоторые константы, свойства, методы и исключения (Exceptions) // не упомянуты с целью выделить только важные для конкретной реализации interface Node { // Типы составляющих XML документа, const unsigned short ELEMENT_NODE = 1; const unsigned short TEXT_NODE = 3; const unsigned short DOCUMENT_NODE = 9; // Свойства и методы XML узла. Для большинства назначение // очевидно из названия. Если не очевидно, воспользуйтесь // их описанием на W3C. readonly attribute DOMString nodeName; attribute DOMString nodeValue; readonly attribute unsigned short nodeType; readonly attribute Node parentNode; readonly attribute NodeList childNodes; readonly attribute Node firstChild; readonly attribute Node nextSibling; readonly attribute NamedNodeMap attributes; readonly attribute Document ownerDocument; Node appendChild(in Node newChild); boolean hasChildNodes(); }; Некоторые вспомогательные или производные от Node типы данных и интерфейсы: // некоторые константы, свойства, методы и исключения (Exceptions) // не упомянуты с целью выделить только важные для конкретной реализации interface NodeList { Node item(in unsigned long index); readonly attribute unsigned long length; }; interface NamedNodeMap { Node getNamedItem(in DOMString name); Node setNamedItem(in Node arg) raises(DOMException); Node removeNamedItem(in DOMString name) raises(DOMException); Node item(in unsigned long index); readonly attribute unsigned long length; }; interface Element : Node { DOMString getAttribute(in DOMString name); void setAttribute(in DOMString name, in DOMString value); }; interface CharacterData : Node { attribute DOMString data; void appendData(in DOMString arg); }; interface Document : Node { readonly attribute Element documentElement; attribute DOMString documentURI; Element createElement(in DOMString tagName); Text createTextNode(in DOMString data); }; interface Text : CharacterData { }; Реализация XML DOM на PHP4 -------------------------- Прежде всего, W3C DOM подразумевает, что язык реализации поддерживает ООП. Наиболее распространенные и известные языки, поддерживающие ООП - это C++, Java. Далее идут .NET, Delphi (Pascal), Python и другие, включая PHP4, который, прямо скажем, не очень приспособлен к ООП. Но, кое что из него выжать можно, в чем мы и убедимся. Для начала, попробуем выбрать только самое необходимое из методов W3C DOM и определить некоторые правила реализации: * NamedNodeMap и NodeList, по всей видимости, не нужны. Их с успехом заменит обычный PHP массив. * DOMException не является необходимым. Достаточно просто вернуть NULL. * Интерфейсы CharacterData и Text не кажутся столь необходимыми. Перенесем и методы непосредственно в Node. * Доступ к свойствам Node сделаем через методы get<Property> и set<Property>, в лучших традициях ООП - не использовать public переменные класса. * Доступ к заявленным read-only свойствам интерфейса Node сделаем read-write - надо же их как-то устанавливать. * getAttribute и setAttribute добавим непосредственно у Node - таким образом Element нам тоже не понадобится. * Полученные классы являются составной частью библиотеки для сайтостроительства, и поэтому будем добавлять к константам и именам класса приставку "SF" (SiteFramework). Аккуратно трансформировав DOM интерфейсы используя заданые правила, получаем необходимые классы и константы: define('SFNODE_ELEMENT', 1); define('SFNODE_TEXT', 2); define('SFNODE_DOCUMENT', 3); class SFNode { function setNodeName($nodeName); function getNodeName(); function setNodeValue($value); function getNodeValue(); function setNodeType($nodeType); function getNodeType(); function setParentNode(&$node); function &getParentNode(); function &getChildNodes(); function &getFirstChild(); function &getNextSibling(); function setNextSibling(&$node); function &getAttributes(); function setOwnerDocument(&$node); function &getOwnerDocument(); function &appendChild(&$newChild); function hasChildNodes(); function setAttribute($name, $value); function getAttribute($name); function appendData($str); } class SFDocument extends SFNode { function &getDocumentElement(); function setDocumentURI($documentURI); function getDocumentURI(); function &createElement($tagName); function &createTextNode($data); } Добавив необходимый код в эти методы получаем аккуратную и необходимую реализацию DOM на PHP. Полученный код классов, загрузчик XML и пример использования можно скачать http://devlink.crimea.ua/files/php_xml.zip (5.2 kB) Примеры использования PHP реализации XML DOM -------------------------------------------- Простой XML загрузчик Для загрузки XML воспользуемся expat (http://sourceforge.net/projects/expat/) XML парсером. Основная идея этого парсера состоит в том, что он разбирает XML документ и вызывает callback функции для начала тега, конца тега, текста и т.д. Что именно делать с тегами и атрибутами решает разработчик, реализовывая произвольный код в вызываемых парсером функциях. Лучше один раз увидеть, чем сто раз услышать, поэтому предлагаю Вашему вниманию основу класса для парсинга XML. Полный вариант загрузчика Вы можете скачать http://devlink.crimea.ua/files/php_xml.zip (5.2 kB). class SFXmlParser { var $xmlDocument; var $currentNode; function parseString($data) { $this->currentNode = null; $this->xmlDocument = new SFDocument(); $xml_parser = xml_parser_create('utf-8'); xml_parser_set_option($xml_parser, XML_OPTION_CASE_FOLDING, 0); xml_set_object($xml_parser, $this); xml_set_element_handler($xml_parser, 'startElementHandler', 'endElementHandler'); xml_set_character_data_handler($xml_parser, 'characterDataHandler'); xml_set_default_handler($xml_parser, 'defaultHandler'); if (!xml_parse($xml_parser, $data, TRUE)) { return new SFException('ERROR: XML error: ' . xml_error_string(xml_get_error_code($xml_parser)) . ' at line ' . xml_get_current_line_number($xml_parser)); } xml_parser_free($xml_parser); return $this->xmlDocument; } function startElementHandler($parser, $name, $attrs) { if (!$this->currentNode) $this->currentNode =& $this->xmlDocument->appendChild( $this->xmlDocument->createElement($name)); else { if ($this->currentNode->getNodeType() == SFNODE_TEXT) $this->currentNode =& $this->currentNode->getParentNode(); $this->currentNode =& $this->currentNode->appendChild( $this->xmlDocument->createElement($name)); } foreach (array_keys($attrs) as $key) $this->currentNode->setAttribute($key, $attrs[$key]); } function endElementHandler($parser, $name) { if ($this->currentNode->getNodeType() == SFNODE_TEXT) $this->currentNode =& $this->currentNode->getParentNode(); $this->currentNode =& $this->currentNode->getParentNode(); } function characterDataHandler($parser, $text) { if ($this->currentNode->getNodeType() == SFNODE_TEXT) $this->currentNode->appendData($text); else $this->currentNode =& $this->currentNode->appendChild( $this->xmlDocument->createTextNode($text)); } function defaultHandler($parser, $data) { return NULL; } } class SFException { var $message; function SFException($message) { $this->message = $message; } function getMessage() { return $this->message; } } // Пример использования $xmlParser = new SFXmlParser(); $xmlDoc =& $xmlParser->parseString('<urls>' . '<url>http://php.net/<;/url>' . '<url>http://phpclub.ru/<;/url></urls>'); if (is_a($xmlDoc, 'SFException')) exit($xmlDoc->getMessage()); Обход XML документа Задача обхода всех узлов является классической при работе с деревом XML документа. Существует, также, 2 варианта решения этой задачи: рекурсивный и не рекурсивный. Приведенный пример рекурсивного обхода вызывает callback функции для каждого узла, начиная некоторого данного узла $node: function walkthrough(&$node, $callbacks) { if ($node->getNodeType() == SFNODE_TEXT) { if (function_exists($fName = $callbacks['text'])) $fName($node); } else { if ($node->getNodeType() == SFNODE_ELEMENT && function_exists($fName = $callbacks['beginTag'])) $fName($node); if ($node->hasChildNodes()) for($n =& $node->getFirstChild(); $n != NULL; $n =& $n->getNextSibling()) walkthrough($n, $callbacks); if ($node->getNodeType() == SFNODE_ELEMENT && function_exists($fName = $callbacks['endTag'])) $fName($node); } } Преобразование XML документа в HTML Используя пример загрузки XML документа и функцию обхода можно составить небольшую программу, обходит XML документ и для каждого узла строит HTML представление. Приведенный пример преобразует список ссылок в вида <url>http://mysite/<;/url> в <a href="http://mysite/">http://mysite/<;/a> // тут код предыдущих примеров function printBeginTag(&$node) { if ($node->getNodeName() == 'url') { $urlNode =& $node->getFirstChild(); $url = $urlNode->getNodeValue(); print '<a href="' . $url . '">' . $url . "</a>\n"; } } walkthrough($xmlDoc->getDocumentElement(), array('beginTag' => 'printBeginTag')); Заключение ---------- XML набирает популярность день за днем и в последнее время становится стандартным методом хранения информации. Например, документ OpenOffice (в котором я набираю текст этой статьи) является XML файлом. Можно предположить, что если Вы будете и дальше заниматься программированием, то все больше и больше Ваших задач будут связаны с построением и обработкой XML документов. Если предложенное решение Вам пригодится в некоторых из них, я буду рад, если Вы мне об этом сообщите. Если у Вас есть комментарии или предложения, касательно материала статьи, Вы всегда можете сообщить о них. Ссылки по теме -------------- http://www.w3c.org/ - World Wide Web Consortium. http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226 - W3C DOM Specification http://www.php.net/ - PHP language site. href="http://phpclub.ru/ - PHP Club, Российское сообщество PHP разработчиков. http://detail.phpclub.net/article/2003-05-12 - XML: спецификация и функции DOM в PHP / Дмитрий Лебедев Copyrights ---------- The article is partly based on the W3C Document <a target="_blank" href="http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226">Object Model (DOM) Level 3 Core Specification Working Draft</a> of 26 February 2003. Copyright 2003 World Wide Web Consortium, (Massachusetts Institute of Technology, European Research Consortium for Informatics and Mathematics, Keio University). All Rights Reserved. http://www.w3.org/Consortium/Legal/2002/copyright-documents-20021231 The article is partly based on the PHP, freely available from http://www.php.net/ Примечания ---------- Основаная цель проекта http://phpmyxml.sourceforge.net/ очень схожа с идеей этой статьи, но значительно шире - реализация DOM, XPath и XSLT рекоммендаций на PHP. Я рекомендую попробовать использовать его, если функциональность классов представленных в этой статье является недостаточной для Вашего проекта.

<< Предыдущая ИНДЕКС Поиск в статьях src Установить закладку Перейти на закладку Следующая >>

Обсуждение [ RSS ]
  • 1, ivenhoe (?), 13:17, 29/12/2004 [ответить]  
  • +/
    О как! Очень актуально! Спасибо!!!
     
  • 2, qMax (?), 15:24, 08/03/2005 [ответить]  
  • +/
    Сейчас работаю над web-приложением с интенсивным интерактивным (относительно сложные формы),
    и пытаюсь среди прочего сделать какую-то реализацию XForms.

    И в расширениях PHP4 и в вашей реализации крайне нехватает поддержки xpath, namespaces, xslt.
    С этими аспектами domxml был бы на порядок более полезен.

     
     
  • 5, Зилибоба (?), 11:26, 03/05/2008 [^] [^^] [^^^] [ответить]  
  • +/
    Вот и расширили бы статейку... увеличилиб объем текста и полезность информации.
     

    игнорирование участников | лог модерирования

     Добавить комментарий
    Имя:
    E-Mail:
    Заголовок:
    Текст:




    Партнёры:
    PostgresPro
    Inferno Solutions
    Hosting by Hoster.ru
    Хостинг:

    Закладки на сайте
    Проследить за страницей
    Created 1996-2024 by Maxim Chirkov
    Добавить, Поддержать, Вебмастеру