PHP5_nachinayushim
.pdf354 Глава 8
в PHP4 задействуют программу Джеймса Кларка (James Clark) expat (синтаксический анализатор XML 1.0, написанный на языке C). Expat+анализаторы могут определить, является ли XML+документ правильно сформированным, но не проверяют коррект+ ность XML+документов. Поэтому анализаторам, созданным на основе expat, необхо+ димо передавать правильно сформированные XML+документы. В противном случае будет сгенерирована ошибка (место возникновения ошибки можно локализовать).
Ниже перечислены некоторые наиболее распространенные функции.
xml_parser_create: базовая функция для создания XML+анализатора, кото+ рый затем можно использовать с другими XML+функциями для чтения и записи данных, определения ошибок, а также для многих других полезных задач. По окончании работы с созданным анализатором рекомендуется использовать функцию xml_parser_free для освобождения ресурсов.
xml_parse_into_struct: разбирает XML+данные в массив. Эту функцию можно использовать для передачи содержимого правильно сформированного XML+файла в PHP+массив, и впоследствии работать с элементами этого массива.
xml_get_error_code: определяет код ошибки XML+анализатора (определяется как константа, например, XML_ERROR_NONE и XML_ERROR_SYNTAX). Чтобы с помощью данного кода получить текстовое описание ошибки, используется функция xml_error_string.
xml_set_option: существует несколько параметров, которые можно задавать для XML+анализатора: XML_OPTION_CASE_FOLDING и XML_OPTION_TARGET_ ENCODING. По умолчанию используется первый параметр. Его включение означа+ ет, что имена элементов будут записываться в верхнем регистре. Второй параметр позволяют указать используемую кодировку для целевого документа; по умолчанию действует кодировка, используемая функцией xml_parser_create ++++++ ISO+8859+1. Чтобы определить, какие параметры для XML+анализатора установлены в те+ кущий момент, можно использовать функцию xml_parser_get_option.
Существует также большое число других, связанных с XML+анализаторами функ+ ций для установки обработчиков различных типов (для распространенных XML+ком+ понентов, например инструкций, символьных данных и т.д.).
Практика Создание XML-документа
Вследующем примере для создания XML+документа используются обычные строки
истроковые функции PHP. Примечательно то, что сценарий работает вообще без XML+ функций. Он получает введенные имена и значения для нескольких элементов и атрибу+ тов, а затем использует эти данные для создания XML+документа, после чего сохраняет этот документ в файле. Недостаток такого сценария в том, что он предоставляет очень слабые возможности по созданию или обработке документов произвольной сложности; можно использовать только два элемента с двумя атрибутами каждый, кроме того, нет никакой проверки корректности документа. Но иногда все, что нужно, это вывести XML+код (как показано ниже, это можно сделать без использования XML+функций).
Для работы данного сценария необходимо создать подкаталог (в Web+каталоге, со+ держащем файл сценария) с именем xml_files. В данном каталоге будут сохраняться созданные XML+файлы (убедитесь в том, что задан правильный каталог по умолча+ нию, $default_dir, если он отличается от указанного в примере). Запустите HTML+ редактор, создайте файл php_xml.php и введите в него следующий код:
XML 355
<html>
<head>
<title>XML-функции PHP</title>
<meta http-equiv="Content-Type" content="text/html; charset=windows-1251"> </head>
<body bgcolor="#FFFFFF">
<form method="POST" action="php_xml.php"> <input type="hidden" name="posted" value="true">
<table width="100%" border="1" cellpadding="10"> <tr><td><h2>Использование XML-средств PHP</h2>
<?php
if (isset($_POST['posted'])) { $cmdButton = $_POST['cmdButton'];
$root_element_name = $_POST['root_element_name']; $element01_name = $_POST['element01_name']; $att0101_name = $_POST['att0101_name']; $att0101_value = $_POST['att0101_value']; $att0102_name = $_POST['att0102_name']; $att0102_value = $_POST['att0102_value']; $element0101_name = $_POST['element0101_name']; $att010101_name = $_POST['att010101_name']; $att010101_value = $_POST['att010101_value']; $att010102_name = $_POST['att010102_name']; $att010102_value = $_POST['att010102_value'];
switch ($cmdButton) {
case "Создать XML-документ"; //формирование XML-документа
$xml_dec = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"; $doc_type_dec = "";
$root_element_start = "<" . $root_element_name . ">"; $root_element_end = "</" . $root_element_name . ">"; $xml_doc = $xml_dec;
$xml_doc .= $doc_type_dec; $xml_doc .= $root_element_start;
$xml_doc .= "<" . $element01_name . " "
. $att0101_name . "=" . "'" . $att0101_value . "'" . " "
. $att0102_name . "=" . "'" . $att0102_value . "'" . ">"; $xml_doc .= "<" . $element0101_name . " "
. $att010101_name . "=" . "'" . $att010101_value . "'" . " "
. $att010102_name . "=" . "'". $att010102_value . "'" . ">"; $xml_doc .= "</" . $element0101_name . ">";
$xml_doc .= "</" . $element01_name . ">";
$xml_doc .= $root_element_end;
//открыть файл, скопировать в него XML-текст, а затем закрыть его $default_dir = "./xml_files";
$fp = fopen($default_dir . "\\" . $_POST['xml_file_name'] . ".xml", 'w');
$write = fwrite($fp, $xml_doc); $response_message = "XML-документ создан";
break;
default;
break;
}
}
?>
<table width="100%" border="1"><tr>
<td><font face="Arial, Helvetica, sans-serif" size="-1"><b>
Создание правильно сформированного XML-документа
</b></font></td>
</tr><tr><td><table width="100%" border="1"><tr>
<td colspan="3"><font size="-1"><b><font face="Arial, Helvetica, sans-serif">Ответ:
<?php echo $response_message; ?></font></b></font></td> </tr><tr>
<td><font size="-1"><b><font face="Arial, Helvetica, sans-serif">
356 Глава 8
Элемент или атрибут</font></b></font></td> <td><font size="-1"><b><font face="Arial, Helvetica,
sans-serif">Имя</font></b></font></td>
<td><font size="-1"><b><font face="Arial, Helvetica, sans-serif">Значение</font></b></font></td>
</tr><tr>
<td><font size="-1"><b><font face="Arial, Helvetica, sans-serif">Корневой элемент:</font></b></font></td>
<td><input type="text" name="root_element_name"> </td><td> </td></tr><tr>
<td><font size="-1"><b><font face="Arial, Helvetica, sans-serif">Элемент01:</font></b></font></td>
<td><input type="text" name="element01_name"> </td><td> </td></tr><tr>
<td><font size="-1"><b><font face="Arial, Helvetica, sans-serif">Атрибут0101:</font></b></font></td>
<td><input type="text" name="att0101_name"> </td><td><input type="text" name="att0101_value"> </td></tr><tr>
<td><font size="-1"><b><font face="Arial, Helvetica, sans-serif">Атрибут0102:</font></b></font></td>
<td><input type="text" name="att0102_name"> </td><td><input type="text" name="att0102_value">
</td></tr><tr><td>
<font size="-1"><b><font face="Arial, Helvetica, sans-serif">Элемент0101: </font></b></font></td>
<td><input type="text" name="element0101_name"> </td><td> </td></tr><tr>
<td><font size="-1"><b><font face="Arial, Helvetica, sans-serif">Атрибут010101:</font></b></font></td>
<td><input type="text" name="att010101_name"> </td><td><input type="text" name="att010101_value"> </td></tr><tr>
<td><font size="-1"><b><font face="Arial, Helvetica, sans-serif">Атрибут010102:</font></b></font></td>
<td><input type="text" name="att010102_name"> </td><td><input type="text" name="att010102_value"> </td></tr><tr>
<td><b><font face="Arial, Helvetica, sans-serif">Текущие XML-файлы</font></b><hr>
<?php
$default_dir = "./xml_files";
if (!($dp = opendir($default_dir))) { die("Невозможно открыть каталог $default_dir.");
}
while ($file = readdir($dp)) {
if ($file != '.' && $file != '..') { echo "$file<hr>";
}
}
closedir($dp); ?>
<font size="-1"><b><font face="Arial, Helvetica, sans-serif">Имя файла нового XML-документа:</font></b></font>
</td><td colspan="2" valign="bottom">
<input type="text" name="xml_file_name" size="30"> </td></tr><tr><td> </td>
<td colspan="2">
<input type="submit" name="cmdButton" value="Создать XML-документ"> </td></tr></table></td></tr> </table>
</td></tr></table>
</form>
</body>
</html>
XML 357
Сохранив данный файл как php_xml.php, запустите его в браузере и с помощью формы (рис. 8.1) создайте правильно сформированный XML+документ.
Рис. 8.1.
Имя первого XML+документа, созданного с помощью данной формы ++++++ first_xml.xml. Если в сценарии использовались те же имена элементов и значения, что и в книге, то файл first_xml.xml будет выглядеть так:
<?xml version="1.0" encoding="UTF-8" ?><rootelement><element01 attr0101="attr0101 val" attr0102="attr0102 val"><element0101 attr010101="attr010101 val" attr010102="attr010102 val" /></element01></rootelement>
Откройте данный .xml+файл в браузере. Результат должен выглядеть аналогично рис. 8.2 при условии, что используемый браузер способен анализировать XML.
358 Глава 8
Рис. 8.2.
Как это работает
Сценарий генерирует стандартную Web+страницу, состоящую из HTML+кода. На стра+ нице отображается таблица с формой, в которую пользователь может вводить имена и значения для фиксированного набора XML+элементов и атрибутов. Функция isset() позволяет определить факт отправки формы, и если форма отправлена, то запускается код. После извлечения значений из $_POST+переменной используется блок switch case, определяющий следующий выполняемый блок сценария. Хотя в данном случае существует только один case+блок, при необходимости такие блоки можно добавить:
<?php
if (isset($_POST['posted'])) { $cmdButton = $_POST['cmdButton'];
$root_element_name = $_POST['root_element_name']; $element01_name = $_POST['element01_name'];
XML 359
$att0101_name = $_POST['att0101_name']; $att0101_value = $_POST['att0101_value']; $att0102_name = $_POST['att0102_name']; $att0102_value = $_POST['att0102_value']; $element0101_name = $_POST['element0101_name']; $att010101_name = $_POST['att010101_name']; $att010101_value = $_POST['att010101_value']; $att010102_name = $_POST['att010102_name']; $att010102_value = $_POST['att010102_value'];
switch ($cmdButton) {
case "Создать XML-документ";
В данном примере в case+блоке выполняется форматирование введенных пользо+ вателем данных в строку, содержащую все необходимые компоненты правильно сформированного XML+документа:
//формирование XML-документа
$xml_dec = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"; $doc_type_dec = "";
$root_element_start = "<" . $root_element_name . ">"; $root_element_end = "</" . $root_element_name . ">"; $xml_doc = $xml_dec;
$xml_doc .= $doc_type_dec; $xml_doc .= $root_element_start;
$xml_doc .= "<" . $element01_name . " "
. $att0101_name . "=" . "'" . $att0101_value . "'" . " "
. $att0102_name . "=" . "'" . $att0102_value . "'" . ">"; $xml_doc .= "<" . $element0101_name . " "
. $att010101_name . "=" . "'" . $att010101_value . "'" . " "
. $att010102_name . "=" . "'". $att010102_value . "'" . ">"; $xml_doc .= "</" . $element0101_name . ">";
$xml_doc .= "</" . $element01_name . ">"; $xml_doc .= $root_element_end;
Затем открывается файл и в него записывается сформированный XML+документ (необходимо правильно указать каталог, используемый по умолчанию, если он отли+ чается от указанного в книге):
//открыть файл, скопировать в него XML-текст, а затем закрыть его $default_dir = "./xml_files";
$fp = fopen($default_dir . "\\" . $_POST['xml_file_name'] . ".xml", 'w'); $write = fwrite($fp, $xml_doc);
Наконец, создается сообщение и данный блок кода заканчивается оператором break:
$response_message = "XML-документ создан"; break;
XML-анализаторы
Итак, очевидно, что XML+документы можно создавать с помощью обычных, стро+ ковых PHP+функций. Однако ясно также и то, что эти функции не представляют простого способа работы с XML+документом. Можно было бы написать какие+либо регулярные выражения и специальные функции, упрощающие работу с XML, но разработчики PHP уже создали множество полезных функций.
В следующем примере демонстрируется использование функций xml_parser_ create() и xml_parse_into_struct(). Кроме того, в приведенном ниже сцена+ рии используется функция file_get_contents(), которая позволяет получить содержимое файла и передать его в строку.
360 Глава 8
Практика Чтение XML-документа
Для изучения данного примера можно скопировать файл php_xml.php под име+ нем php_xml02.php. Затем в него необходимо будет вставить новый case+блок и но+ вую таблицу для отображения результатов.
1.Создайте копию файла php_xml.php, сохраните ее с именем php_xml02.php
иоткройте в HTML+редакторе.
2.Вставьте следующий код вместо прежнего блока, который начинается с if (isset
изаканчивается switch ($cmdButton):
if (isset($_POST[posted])) {
$xml_file_chosen = $_POST[xml_file_chosen]; $cmdButton = $_POST[cmdButton];
switch ($cmdButton) {
3. Теперь вместо прежнего case+блока вставьте следующий код:
case "Проанализировать XML-документ";
//найти заданный файл $default_dir = "./xml_files";
$xml_string = file_get_contents ($default_dir . "/" . $xml_file_chosen,"rb");
//Прочитать имеющиеся данные и превратить их в массивы $xp = xml_parser_create();
xml_parse_into_struct($xp, $xml_string, $values, $keys); xml_parser_free($xp);
break;
4. Вместо прежней HTML+таблицы вставьте новую, код которой показан ниже:
<table width="100%" border="1">
<tr><td><font face="Arial, Helvetica, sans-serif" size="-1"> <b>Проанализировать XML-документ</b></font></td></tr><tr><td>
<table width="100%" border="1"><tr><td>
<font face="Arial, Helvetica, sans-serif" size="-1"> <b>Выберите XML-файл</b></font></td></td>
<td><select name="xml_file_chosen">
<?php
$default_dir ="./xml_files";
if (!($dp = opendir($default_dir))) { die("Невозможно открыть каталог $default_dir.");
}
while ($file = readdir($dp)) {
if ($file != '.' && $file != '..') {
echo "<option value='$file'>$file</option>\n";
}
}
closedir($dp); ?>
</select></td></tr><tr>
<td><font face="Arial, Helvetica, sans-serif" size="-1"> <b>Содержимое XML-файла</b></font><hr>
<?php
if ($cmdButton == "Проанализировать XML-документ") {
XML 361
echo "Массив ключей<BR><BR><PRE>";
print_r($keys);
echo "</PRE><BR><BR>Массив значений<BR><BR><PRE>"; print_r($values);
echo "</PRE>";
}
?>
</td><td>
<input type="submit" name="cmdButton" value="Проанализировать XML-документ"> </td></tr></table>
</td></tr></table>
5.Сохраните данный файл и вызовите его в браузере. Значение атрибута action необходимо изменить на новое имя файла, php_xml02.php. На странице в выпа+ дающем списке должен отобразиться XML+файл, созданный с помощью исходно+ го сценария php_xml.php (а также остальные файлы, если было создано не+ сколько XML+файлов). Выберите файл и нажмите кнопку Проанализировать
XML-документ. На рис. 8.3 показаны выводимые на экран массивы ключей и значений.
Рис. 8.3.
362 Глава 8
Как это работает
Case+блок начинается с поиска выбранного пользователем файла и считывания из него данных в переменную $xml_string. После этого для создания нового объекта+ анализатора (с именем $xp) используется функция xml_parser_create, а функция xml_parse_into_struct() превращает XML+документ в два массива: массив ключей и массив значений.
Функция xml_parse_into_struct() принимает в качестве аргументов XML+ана+ лизатор (объектная переменная $xp), строковую переменную (содержимое XML+докумен+ та), а также имена двух массивов, которые необходимо создать:
//найти заданный файл $default_dir = "./xml_files"; $xml_string = file_get_contents
$xml_file_chosen,"rb");
($default_dir . "/" .
//Прочитать имеющиеся данные и превратить их в массивы $xp = xml_parser_create();
xml_parse_into_struct($xp, $xml_string, $values, $keys); xml_parser_free($xp);
break;
HTML+таблица предоставляет средство для выбора необходимого .xml+файла. За+ тем, если была нажата кнопка Проанализировать XML-документ, сценарий посред+ ством функции print_r() распечатывает на экране два массива. Для того чтобы дан+ ные отображались в удобочитаемом виде, используется HTML+тег <PRE>:
<table width="100%" border="1">
<tr><td><font face="Arial, Helvetica, sans-serif" size="-1"> <b>Проанализировать XML-документ</b></font></td></tr><tr><td>
<table width="100%" border="1"><tr><td>
<font face="Arial, Helvetica, sans-serif" size="-1"> <b>Выберите XML-файл</b></font></td></td>
<td><select name="xml_file_chosen">
<?php
$default_dir = "./xml_files";
if (!($dp = opendir($default_dir))) { die("Невозможно открыть каталог $default_dir.");
}
while ($file = readdir($dp)) {
if ($file != '.' && $file != '..') {
echo "<option value='$file'>$file</option>\n";
}
}
closedir($dp); ?>
</select></td></tr><tr>
<td><font face="Arial, Helvetica, sans-serif" size="-1"> <b>Содержимое XML-файла</b></font><hr>
<?php
if ($cmdButton == "Проанализировать XML-документ") { echo "Массив ключей<BR><BR><PRE>";
print_r($keys);
echo "</PRE><BR><BR>Массив значений<BR><BR><PRE>"; print_r($values);
echo "</PRE>";
XML 363
}
?>
</td><td>
<input type="submit" name="cmdButton" value="Проанализировать XML-документ"> </td></tr></table>
</td></tr></table>
Объектная модель документа
Объектная модель документа(Document Object Model, DOM) представляет собой иерархическую модель для взаимодействия с документами. Она делает возможным доступ к частям документа путем непосредственного обращения к ним.
XML+документы можно моделировать с помощью DOM, так как между частями лю+ бого XML+документа существуют специфические отношения. Как уже было показано, может существовать только один корневой элемент, и он является родительским для всех остальных элементов в XML+документе. Это означает, что корневой документ находится внизу (отсюда и название) иерархии или дерева, из которого ‘‘произрас+ тают’’ остальные элементы. Следовательно, отношения между компонентами XML+ документа могут быть выведены программно (именно это и делают функции DOM+ расширения PHP; это расширение подробнее рассматривается далее).
Элементы, расположенные внутри другого элемента, являются дочерними для этого элемента, тогда как элемент, внутри которого он расположен, является для него роди+ тельским. Поэтому элементы можно представлять как родителей и детей или как де+ рево с корнем, ветвями и листьями. Внутри модели DOM допустимы обе абстракции. Элементы и другие компоненты XML+документа внутри модели DOM считаются узлами.
DOM-расширение
DOM+расширение в PHP строго придерживается рекомендации Консорциума W3C, касающейся второго уровня DOM, которая гласит: ‘‘Модель DOM представляет собой API (application programming interface ++++++ программный интерфейс приложений) для корректных HTML+ и правильно сформированных XML+документов’’. DOM позво+ ляет программно создавать и осуществлять навигацию в любом правильно сформиро+ ванном XML+документе, а также добавлять, редактировать и удалять из него узлы.
Чтобы данное расширение было доступно в сценариях, необходимо скомпилиро+ вать PHP с параметром --with-dom=dom_dir. Для инсталляции PHP в Windows не+ обходимо скопировать файл libxml2.dll или iconv.dll в каталог System32. Даль+ нейшие инструкции приведены в документации.
Поддержка функций DOM+расширения на момент написания книги остается экс+ периментальной (поэтому в данной книге нет примеров его использования), в книге
Профессиональное программирование на PHP (ИД ‘‘Вильямс’’, 2006 г) DOM+расширение PHP освещается более подробно.
Использование функций DOM-расширения PHP
В PHP имеются следующие DOM+функции: domxml_new_doc() для создания новых XML+документов, domxml_open_file() для открытия файла XML+документа в виде DOM+объекта, а также domxml_open_mem() для создания DOM+объекта из уже имеюще+ гося в памяти XML+документа. Функции возвращают DOM+объект, а не строку или дан+ ные другого типа. Чтобы использовать PHP DOM+функции, обычно сначала необходимо создать объект DOMDocument, а затем манипулировать им, используя методы, которые