OpenNET: стаття - Альтернатива DOM XML на PHP (PHP4) (xml php)

Альтернатива DOM XML на PHP (PHP4) (xml php)
Ключові слова: 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/&lt ; / Url> '. '<Url> http://phpclub.ru/&lt ; / 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 / & lt ; / Url> в <a href = " http: // mysite / "> http: // mysite / & lt ; / 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. Я рекомендую спробувати використовувати його, якщо функціональність класів представлених в цій статті є недостатньою для Вашого проекту.

Обговорення [ RSS ]

  • 2 , qMax (?), 15:24 08/03/2005 [ відповісти ]
+

/ - /   -   Зараз працюю над web-додатком з інтенсивним інтерактивним (щодо складні форми),   і намагаюся серед іншого зробити якусь реалізацію XForms Зараз працюю над web-додатком з інтенсивним інтерактивним (щодо складні форми),
і намагаюся серед іншого зробити якусь реалізацію XForms.

І в розширеннях PHP4 і в вашій реалізації вкрай бракує підтримки xpath, namespaces, xslt.
З цими аспектами domxml був би на порядок більше корисний.

  • 5 , Зілібоба (?), 11:26, 03/05/2008 [ ^ ] [ ^^ ] [ ^^^ ] [ відповісти ]
+

/ - Ось і розширили б статейку ... увелічіліб обсяг тексту і корисність інформації.


Додати коментар

Спонсори:

Хостинг:



Дополнительная информация

rss
Карта