Главная страница статей --> Хитрости при программировании php, заметки по базам данных

Обработка запросов к БД при помощи PEAR::XML

Источник: realcoding.net

[2 страница]
<?php

// Создание объекта документа из текстовой строки
$xmldoc = domxml_open_mem(<?xml version=1.0 encoding=windows-1251?>);

// Cсылку на корневой узел документа записываем в переменную $my_root (название
//переменной значения не имеет).
$my_root = $xmldoc->document_element();

// Создаём текстовый узел.
$my_element = $xmldoc->create_text_node(iconv(windows-1251, UTF-8,
   
Это содержимое корневого узла XML-документа.));

// Присоединяем текстовый узел к корневому.
$my_root->append_child($my_element);

print(
$xmldoc->dump_mem());

?>

Следующий пример показывает, как можно удалять элементы:

<?php

$xmldoc
= domxml_open_mem(<?xml version=1.0 encoding=windows-1251?>
Нечто
);

$my_root = $xmldoc->document_element();

// В массив $children записываются все потомки узла my_root.
$children = $my_root->child_nodes();

// Уничтожается первый потомок (узел something)
$children[0]->unlink_node();

// Создаётся новый узел под названием new и записывается в переменную $new
$new = $my_root->append_child($xmldoc->create_element(new));

// К этому узлу добавляется потомок — текстовый узел
$new->append_child($xmldoc->create_text_node(iconv(windows-1251, UTF-8,
   
Это содержимое нового узла XML-документа.)));

print(
$xmldoc->dump_mem());

?>

в результате получится такой XML-документ:

<?xml version=1.0 encoding=windows-1251?>
<my_root><new>Это содержимое нового узла XML-документа.</new></my_root>

Кстати, если изменить исходный XML-документ на такой:

<?php

$xmldoc
= domxml_open_mem(<?xml version=1.0 encoding=windows-1251?>

    Нечто

);

?>

Результат будет иным:

<?xml version=1.0 encoding=windows-1251?>
<my_root><something>Нечто</something>
<new>Это содержимое нового узла XML-документа.</new></my_root>

Предоставляю вам возможность догадаться, почему это произошло.

Конечно же, приведённые примеры — самое простое из того, что можно делать в DOM XML. Кроме построения нового это и самые хитрые преобразования документа, и XSL-трансформация при помощи библиотеки libxslt, не уступающей в функциональности Sablotron, а в скорости превосходящей его в два раза. Перед нами открываются огромные возможности по работе с документом, проблема — как организовать и систематизировать эту работу.

На ум приходит следующая схема преемника классов шаблонов: вызывается скрипт, который открывает стандартный XML-файл и включает буферизацию данных. Все скрипты тупо выдают XML-данные в print. Вызывается второй скрипт, который останавливает буферизацию, берёт данные из буфера, дописывает к ним в начале "<?xml version="1.0" encoding="windows-1251"?><root>" и "</root>" в конце, затем преобразует в объект DOM, открывает корневой элемент и берёт всех массив потомков. Полученные узлы вставляет в основной XML-документ (который тоже открыт как объект), результат преобразует через XSLT и выдаёт пользователю.

На этом заканчиваем краткое описание DOM XML и переходим к классу sql2xml.
Класс SQL2XML

Вся функциональность, которая нужна для преобразования результатов SQL-запросов в XML, есть в этом классе. Для соединения с базой данных класс использует либо существующее соединение класса PEAR::DB, либо своё собственное (точнее, он создаёт в себе объект класса DB). Из результата запроса строится XML-дерево. Пример из руководства по классу:

mysql> select * from bands;
+----+--------------+------------+-------------+-------------+
id name birth_year birth_place genre
+----+--------------+------------+-------------+-------------+
1 The Blabbers 1998 London RocknRoll
2 Only Stupids 1997 New York Hip Hop
+----+--------------+------------+-------------+-------------+

mysql> select * from albums;
+----+---------+------------------+------+-----------------+
id bandsID title year comment
+----+---------+------------------+------+-----------------+
1 1 BlaBla 1998 Their first one
2 1 More Talks 2000 The second one
3 2 All your base... 1999 The Classic
+----+---------+------------------+------+-----------------+

Это набор данных. А теперь вызов класса и результаты работы. php-код:

<?php
include_once(XML/sql2xml.php);
$sql2xmlclass = new xml_sql2xml(mysql://username:password@localhost/xmltest);
$xmlstring = $sql2xmlclass->getxml(select * from bands);
?>

XML-документ:

<?xml version=1.0?>
    <root>
        <result>
            <row>
                <id>1</id>
                <name>The Blabbers</name>
                <birth_year>1998</birth_year>
                <birth_place>London</birth_place>
                <genre>RocknRoll</genre>
            </row>
            <row>
                <id>2</id>
                <name>Only Stupids</name>
                <birth_year>1997</birth_year>
                <birth_place>New York</birth_place>
                <genre>Hip Hop</genre>
            </row>
        </result>
    </root>

Результат выводится и в текстовом виде, и как DOM-объект (что весьма удобно при генерации документов через DOMXML). Так же можно из всего XML-дерева выдернуть одно значение при помощи выражения XPath. Ещё очень хорошая особенность: раз уж строятся деревья, и всё оперируется в XML, почему бы запросы с объединением "один-ко-многим" не делать в виде вложенных друг в друга узлов <row>. php-код:

<?php
include_once(XML/sql2xml.php);
$sql2xml = new xml_sql2xml(mysql://username:password@localhost/xmltest);
$xmlstring = $sql2xml->getxml(select * from bands left join albums on bands.id = bandsID);
?>

XML-документ:

<?xml version=1.0?>
    <root>
        <result>
            <row>
                <id>1</id>
                <name>The Blabbers</name>
                <birth_year>1998</birth_year>
                <birth_place>London</birth_place>
                <genre>RocknRoll</genre>
                <row>
                    <id>1</id>
                    <bandsID>1</bandsID>
                    <title>BlaBla</title>
                    <year>1998</year>
                    <comment>Their first one</comment>
                </row>
                <row>
                    <id>2</id>
                    <bandsID>1</bandsID>
                    <title>More Talks</title>
                    <year>2000</year>
                    <comment>The second one</comment>
                </row>
            </row>
            <row>
                <id>2</id>
                <name>Only Stupids</name>
                <birth_year>1997</birth_year>
                <birth_place>New York</birth_place>
                <genre>Hip Hop</genre>
                <row>
                    <id>3</id>
                    <bandsID>2</bandsID>
                    <title>All your base...</title>
                    <year>1999</year>
                    <comment>The Classic</comment>
                </row>
            </row>
        </result>
    </root>

Впрочем, если вы хотите получить обычный результат запроса, это свойство можно отключить. Если имена узлов для результата и для ряда вас не устраивают, можно их поменять. Если вас не устраивает формат (всё в текстовых узлах, а не, например, в атрибутах), можно преобразовать полученный DOM-объект в нужный вам. На мой взгляд, этого не понадобится, поскольку если на сайте до этого уже использовался XSLT, исправить XSL-файл не представляет особой сложности.

Итак, класс вполне пригоден к использованию. Если он вас чем-то не устраивает, можно, глядя на существующий, написать свой собственный. Исправлять данный класс вполне можно, поскольку манипуляции с DOM-объектами не намного сложнее внутреннего устройства классов шаблонов. Я для себя исправил ошибки call-time pass-by-reference в классе версии 0.3 (версия 0.3.1 — это как раз мой багфикс) а так же заменил старые не поддерживаемые функции и конструкции DOM XML на новые. Сейчас работаю над тем, как справиться с проблемой кодировки документа (объект документа там создаётся функцией domxml_new_doc, а для создания из текстовой строки требуется основательно переделать существующую в классе sql2xml функцию).

Контакты
Редакция:
[0.001]