
web - tec / PHP 5 для начинающи
.pdf
XML 353
приложение, теоретически распределенное в Internet (т.е. независимое от того, где расположена программная логика или хранятся данные).
Это именно то, что можно сделать с помощью Web+служб. Вызов функций, написанных другим разработчиком, использование созданных другими программистами баз данных или даже использование множества функций и баз данных в любой точке Internet ++++++ вот для чего предназначены Web+службы. Однако для доступа к Web+службам требуется специ+ альное средство, потому что Web+службы могут работать на разных платформах, ис+ пользовать любые языки и базы данных; кроме того, имеются некоторые проблемы при передаче данных. Здесь полезными оказываются технологии SOAP и WSDL.
SOAP (Simple Object Access Protocol ++++++ простой протокол доступа к объек+ там) ++++++ XML+язык, позволяющий определять для отправки и получения кон+ верт, тело и другие компоненты вызовов Web+служб. Вызовы Web+служб поме+ щаются в SOAP+конверт.
WSDL (Web Service Description Language ++++++ язык описания Web+служб) ++++++ дру+ гой XML+язык, который используется для определения имени, типа и аргумен+ тов, связанных с вызовом Web+службы.
Web+службы являются одним из наиболее важных аспектов применения XML. Су+ ществует множество доступных связанных с Web+службами приложений, которые об+ легчают разработку на PHP как Web+служб, так и обращающегося к этим службам кли+ ентского кода. (Тема Web+служб выходит за рамки данной книги, более подробная информация по этой теме представлена в книге Professional PHP Development.)
PHP и XML
Почти с самого начала существования PHP в данном языке присутствуют встроен+ ные функции для подключения, получения данных и манипуляции данными в базах данных. Позднее, по мере того как спецификация XML приобретала широкую попу+ лярность как средство обмена данными и хранения данных, в PHP появлялись функ+ ции, облегчающие работу с XML+документами.
Ввиду специфической природы и формата XML+документов большая часть работы по добавлению XML+функций в PHP сосредоточена на правильном синтаксическом анализе XML+документов и их обработке с сохранением соответствия со специфика+ цией XML. Чтобы эффективно анализировать и обрабатывать XML+документы, дан+ ные функции должны быть способны работать с именами и значениями элементов и атрибутов, а также со многими другими компонентами XML+документов.
Далее рассматриваются XML+фукнции, которые были встроены в PHP в течение нескольких последних лет, включая такие нововведения, как расширение simpleXML. Сначала обсуждаются XML+фукнции, которые были встроены в PHP4, затем рассмат+ риваются расширения simpleXML и DOM (Document Object Model ++++++ документная объектная модель) и, наконец, расширения PHP5.
XML-функции в PHP4
PHP5 сохраняет обратную совместимость с многими функциями PHP4, поэтому дан+ ный раздел начинается с обсуждения некоторых XML+фукнций PHP4, после чего рассмат+ риваются новые XML+функции, доступные в PHP5. Функции семейства xml_parser

354 Глава 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>";