Что происходит, если взаимодействие PHP и XML осуществляется с помощью объектной модели стандарта DOM? Модуль DOM XML определяет в PHP несколько классов, таких как DomNode, DomDocument, DomElement, DomText и DomAttribute, большинство из которых идут из ядра стандарта DOM. Почти для всех классов (в частности, для перечисленных выше) класс DomNode является родительским, поэтому его свойства и методы наследуются всеми остальными классами.
Если рассмотреть произвольный XML-документ, то классу DomDocument будет соответствовать сам этот документ, классу DomElement – каждый XML-тег, классу DomAttribute – атрибуты тегов, а классу DomText – содержание XML-элементов. В то же время классу DomNode будет соответствовать каждый из перечисленных элементов XML-документа.
Рассмотрим коллекцию, содержащую описания персон. Если каждую из них мы описываем с помощью таких характеристик, как фамилия, имя, дата рождения и электронный адрес, то структура коллекции «Личности», где хранится информация обо всех известных нам персонах, может быть представлена следующим образом.
Пример 14.2. Коллекция «Личности» в виде XML-файла (persons.xml) (html, txt)
В дальнейшем, приводя примеры, мы будем использовать этот файл.
Нам необходимо научиться читать, добавлять, изменять и искать информацию, находящуюся в XML-файлах.
Перевод данных XML-файла в объекты и классы PHP
Первое, что нужно сделать, если мы хотим работать с XML-данными в PHP при помощи расширения DOM XML, это перевести имеющиеся данные в объекты и классы DOM. Это можно сделать несколькими способами.
С помощью функции domxml_open_mem.
Синтаксис:
object domxml_open_mem (string str)
В качестве параметра эта функция принимает строку str, содержащую XML-документ. Результатом ее работы является объект класса, называемого DOMDocument.
С помощью функции domxml_open_file.
Синтаксис:
object domxml_open_file (string filename)
Эта функция обрабатывает XML-файл, имя которого задается параметром filename, и переводит его в объект класса DOMDocument. Доступ к файлу производится только на чтение.
Такие функции, как domxml_open_mem() и domxml_open_file(), как правило, нужно вызывать перед вызовом любых других функций, связанных с расширением DOM.
Эти функции преобразуют XML-файл в дерево объектов. К таким объектам можно обращаться с помощью различных методов. В частности, для выделения корневого элемента используется метод DomDocument->document_element().
Еще существует функция domxml_new_doc(string version), которая создает новый пустой XML-документ. Ее параметром является номер версии создаваемого документа. Но ее мы касаться не будем, а будем считать, что XML-файл уже создан.
<?//считываем файл "persons.xml" в строку$xmlstr = join('',file('persons.xml'));// переводим строку с xml-файлом// в дерево объектов. Если операция// прошла неудачно, то выводим// ошибку и прекращаем работу.if(!$dom = domxml_open_mem($xmlstr)) { echo "Ошибка при разборе документа\n"; exit;}// можно посмотреть, как выглядит// этот объектprint_r($dom);echo "<hr>";// выделяем корневой элемент// дерева объектов.// В нашем случае это будет// элемент <collection>$root = $dom->document_element();print_r($root);echo "<hr>";?>
Пример 14.3. Перевод XML-файла в дерево объектов PHP и выделение корневого элемента (html, txt)
Итак, каждому элементу XML-файла мы поставили в соответствие какой-то объект. Теперь нужно научиться перемещаться по дереву объектов и обращаться с этими объектами: получать и изменять их значения, находить их потомков и предков, удалять объекты.
Обход дерева объектов
Для получения значения текущего узла (вне зависимости от его типа) используют метод DomNode->node_value() или DomNode->get_content() для получения содержимого узла.
Для получения значения атрибута используется метод DomElement->get_attribute (attr_name). А метод DomNode->child_nodes() возвращает массив потомков данного узла.
Для того чтобы сделать обход дерева объектов, полезно еще уметь различать объекты по типам, т.е. определять, является ли узел элементом (тегом), текстом, атрибутом и т.п. Для этого используются специальные константы. XML_ELEMENT_NODE определяет, является ли узел элементом, XML_ATTRIBUTE_NODE определяет, является ли узел атрибутом, и XML_TEXT_NODE определяет, является ли узел куском текста. Эти константы имеют целочисленные значения 1, 2 и 3 соответственно. Использование этих констант полезно, поскольку переводы строки, применяемые для удобочитаемости XML-файлов, тоже становятся узлами.
<?// сначала делаем то же,// что и в предыдущем примере$xmlstr = join('',file('persons.xml'));if(!$dom = domxml_open_mem($xmlstr)) { echo "Ошибка при разборе документа\n"; exit;}$root = $dom->document_element();// Получаем массив потомков// родительского узла// (в нашем случае это массив <person>)$nodes = $root->child_nodes();print_r($nodes);echo "<hr>";// Начинаем обработку каждого// узла в массивеforeach($nodes as $node){ // Если текущий узел – один // из узлов <person>, то // продолжаем ее обработку, // чтобы получить информацию // об этой личности if ($node->tagname=='person'){ // Создаем массив, куда // будем собирать информацию // о рассматриваемой личности $currentPers = array(); // Получаем id личности, // который хранится в атрибуте 'id' $currentPers['id'] = $node->get_attribute('id'); // Получаем массив потомков // <person>. Это вся // информация о личности // (<name>,<birth> и т.д.) $persons_info = $node->child_nodes(); // Перебираем все дочерние // узлы $node foreach ($persons_info as $info){ // проверяем, является ли узел // элементом (xml-тегом) if ($info->type== XML_ELEMENT_NODE) { // тогда метод tagname // возвратит имя этого // элемента (тега), а метод // get_content() – // его содержимое $currentPers[$info->tagname] = $info->get_content(); } } // выводим на экран полученные // массивы print_r ($currentPers); echo "<br>"; }}?> Пример 14.4. Обход дерева XML (html, txt)
Итак, мы научились обходить дерево XML. Теперь можно попытаться что-нибудь найти в XML-файле. Правда, делать это не совсем удобно опять же из-за переносов строк, которые мы использовали при написании XML-файла. Пусть наш XML-файл записан в строку, а точнее, в нем есть следующая строка:
...<person id="20"> <name> <first>Иван</first> <last>Иванов</last> </name>... Тогда в наш предыдущий пример вставим (после вывода на экран полученных массивов) строчку для поиска электронного адреса Ивана Иванова.
... $str = $currentPers["email"]; if ($currentPers["name"] == "Иван Иванов") echo "Здравствуйте Иван! ". "Ваш e-mail $str";... Добавление новых элементов в XML-документ
Далее разберем задачу, как можно добавить в нашу базу данных новую личность средствами php.
Сначала нужно скопировать описание личности (считаем, что все личности описываются с помощью стандартного набора характеристик, как в файле persons.xml). Это делается с помощью метода DomNode->clone_node(). Таким образом, мы клонируем элемент <person> и все его внутренние элементы (содержание тегов не копируется).
Потом можно установить какие-нибудь значения для элементов описания личности. Например, задать имя человека, дату его рождения и т.п. В конце нужно записать полученное описание личности в качестве потомка корневого элемента в дерево DOM с помощью метода DomNode->append_child(new_node), где в качестве параметра передается созданный объект (новый узел).
В PHP до версии 4.3 перед добавлением потомка к узлу с помощью данной функции этот потомок сначала копировался. Таким образом, новый узел являлся новой копией, которая могла изменяться без изменения узла, переданного как параметр в эту функцию. В более поздних версиях PHP новый узел удаляется из существующего контекста, если он уже есть в дереве. Такое поведение соответствует спецификациям W3C.
Для удаления узла можно воспользоваться методом, применив его к узлу, который требуется удалить, т.е. DomNode->unlink_node().
Пример 14.5. Добавление описания новой личности в каталог (html, txt)
// Для того чтобы добавить описание// новой личности, нужно знать,// как описывается каждая личность.// Выбираем элемент person,// который содержит описание личности$elements =$dom->get_elements_by_tagname("person");$element = $elements[0];//вычисляем родителя и потомков$parent = $element->parent_node();$children = $element->child_nodes();// клонируем элемент person$person = $element->clone_node();// устанавливаем новой// личности идентификатор$attr = $person->set_attribute("id", "30");// если у личности были потомки,// то их тоже надо клонироватьforeach ($children as $child){ //клонируем ребенка $node = $child->clone_node(); //получаем массив внуков $grand_children = $child->child_nodes(); // если ребенок имеет потомков, //т.е. массив внуков не пуст, то if (count($grand_children)<>1){ //клонируем каждого внука //и присоединяем к уже //клонированному ребенку foreach($grand_children as $grand_child){ $lastnode = $grand_child->clone_node(); //записываем в нужные теги //подходящие значения if ($grand_child->tagname=="first") $cont = $lastnode->set_content("Nina"); if ($grand_child->tagname=="last") $cont = $lastnode->set_content("Saveljeva"); if ($grand_child->tagname=="day") $cont = $lastnode->set_content("7"); if ($grand_child->tagname=="month") $cont = $lastnode->set_content("06"); if ($grand_child->tagname=="year") $cont = $lastnode->set_content("1981"); $newlastnode = $node->append_child($lastnode); } } if ($child->tagname=="email") { $cont = $node->set_content("help@intuit.ru"); } $newnode2 = $person->append_child($node);}$newnode = $parent->append_child($person);//dump_mem создает XML-документ из dom//представленияecho "<PRE>";$xmlfile = $dom->dump_mem(true);// посмотрим в браузере,// что получилосьecho htmlentities($xmlfile);echo "</PRE>";// запишем полученный XML-файл// в файл "test.xml"$h = fopen("test.xml","a");if (!fwrite($h, $xmlfile)) { print "Cannot write ". "to file ($filename)"; exit; }}
Заключение
Итак, мы изучили ряд функций, позволяющих манипулировать данными, хранящимися в XML-формате. Это, конечно же, далеко не полный перечень существующих функций. В версии PHP5 он значительно усовершенствован и в большей степени соответствует стандарту DOM. Тем не менее знание приведенных здесь основных функций может оказаться полезным при решении конкретных прикладных задач.
studopediasu.com - Студопедия (2013 - 2026) год. Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав!Последнее добавление