XML (eXtensible Markup Language) это формат данных для обмена
структурированными документами в Web. Это стандарт, созданный консорциумом World Wide Web consortium (W3C).
Информация о XML и сопутствующих технологиях находится на сайте
http://www.w3.org/XML/
Это расширение использует библиотеку expat, которую можно найти на
http://www.jclark.com/xml/.
Makefile, который поставляется вместе с expat, не строит библиотеку по умолчанию. Вы можете использовать такое make-правило:
Заметьте, что при использовании Apache-1.3.7 или новее у вас уже имеется
соответствующая библиотека expat. Просто сконфигурируйте PHP с использованием
--with-xml (без дополнительного пути), и он будет автоматически использовать библиотеку expat, встроенную в Apache.
В UNIX - запустите configure с опцией --with-xml. Библиотека
expat должна быть установлена в таком месте, где компилятор сможет её найти. Если
вы компилируете PHP как модуль для Apache 1.3.9 или новее, PHP будет
автоматически использовать связанную библиотеку expat из Apache. Вам может понадобиться установка флагов
CPPFLAGS и LDFLAGS в вашем окружении до запуска configure, если вы установили expat как-то экзотично.
Это расширение PHP реализует поддержку expat James’а Clark’а в PHP. Этот набор утилит позволяет разбирать, но не проверять, XML-документы.
Он поддерживает три исходные кодировки символов,
также предоставляемые PHP: US-ASCII, ISO-8859-1 и UTF-8. UTF-16 не поддерживается.
Это расширение позволяет создавать XML-разборщики и определять обработчики различных XML-событий. Каждый XML-разборщик
также имеет несколько параметров, которые вы можете настроить.
События элементов возникают, когда XML-разборщик обнаруживает начальный или конечный тэги. Для начальных и конечных тэгов имеются
отдельные обработчики.
Символьные данные это, ориентировочно, всё неразмеченное содержимое
XML-документов, включая пробелы между тэгами. Заметьте, что XML-разборщик не добавляет и не удаляет пробелы,
это обязанность приложения (ваша) - решить, имеет ли пробел значение.
PHP-программисты должны быть уже знакомы с инструкциями процессинга/processing
instructions (PI). <?php ?> это инструкция процессинга, где php это вызванная "цель PI". Их обработка зависит от приложения, за исключением
того, что все цели PI, начинающиеся с "XML", зарезервированы.
Этот обработчик вызывается, когда XML-разборщик находит ссылку на
внешний разбираемый общий экземпляр. Это может быть ссылка на файл или URL,
например. См. демонстрацию в примере внешнего экземпляра.
Функции обработчиков элементов могут получать имена своих элементов
case-folded. Case-folding определяется стандартом XML как "процесс, применяемый к
последовательности символов, когда те из них, которые идентифицируются как non-uppercase/не
в верхнем регистре, заменяются своими эквивалентами верхнего регистра". Иначе
говоря, если речь идёт о XML, case-folding означает перевод в верхний регистр.
По умолчанию все имена элементов, передаваемые функциям обработчиков,
передаются с выравниванием регистра. Это поведение может запрашиваться и
контролироваться XML-разборщиком с помощью функций
xml_parser_get_option() и
xml_parser_set_option(), соответственно.
XML-расширение РНР поддерживает набор символов
Unicode через различные кодировки символов. Есть два типа кодировок символов,
кодировка источника и кодировка цели.
Внутреннее представление документа в PHP всегда кодируется в UTF-8.
Кодировка источника делается, когда XML-документ разбирается. После
создания XML-разборщика кодировка источника может быть специфицирована (эта кодировка не может быть
изменена позднее, в период существования XML-разборщика). Поддерживаются кодировки источника ISO-8859-1,
US-ASCII и UTF-8. Первые две это однобайтные кодировки, то есть каждый символ представлен
одним байтом. UTF-8 может кодировать символы, составленные из переменного количества бит (до 21) в
1-4 байтах. По умолчанию кодировка источника в РНР - ISO-8859-1.
Целевая кодировка выполняется, когда PHP передаёт данные функциям XML-обработчиков.
Когда XML-обработчик создаётся, устанавливается та же самая целевая кодировка,
что и исходная кодировка, но она может быть изменена в любой момент. Целевая
кодировка влияет на символьные данные и на имена тэгов и цели инструкций процессинга.
Если XML-разборщик находит символы вне диапазона представления исходной кодировки, он возвратит ошибку.
Если PHP находит в разбираемом XML-документе символы, которые не могут
быть представлены в избранной целевой кодировке, проблемные символы будут "понижены
в звании". В настоящее время это означает, что такие символы заменяются знаком вопроса.
Этот пример отображает тэги XML-документа непосредственно в тэги HTML.
Элементы, не найденные в "массиве отображения", игнорируются. Конечно,
этот пример будет работать только со специфическим типом XML-документов.
$file = "data.xml";
$map_array = array(
"BOLD" => "B",
"EMPHASIS" => "I",
"LITERAL" => "TT"
);
function startElement($parser, $name, $attrs) {
global $map_array;
if ($htmltag = $map_array[$name]) {
print "<$htmltag>";
}
}
function endElement($parser, $name) {
global $map_array;
if ($htmltag = $map_array[$name]) {
print "</$htmltag>";
}
}
function characterData($parser, $data) {
print $data;
}
$xml_parser = xml_parser_create();
// использовать выравнивание регистра, чтобы гарантированно найти тэг в $map_array
xml_parser_set_option($xml_parser, XML_OPTION_CASE_FOLDING, true);
xml_set_element_handler($xml_parser, "startElement", "endElement");
xml_set_character_data_handler($xml_parser, "characterData");
if (!($fp = fopen($file, "r"))) {
die("could not open XML input");
}
while ($data = fread($fp, 4096)) {
if (!xml_parse($xml_parser, $data, feof($fp))) {
die(sprintf("XML error: %s at line %d",
xml_error_string(xml_get_error_code($xml_parser)),
xml_get_current_line_number($xml_parser)));
}
}
xml_parser_free($xml_parser);
Этот пример разъясняет XML-код. Он показывает, как использовать
обработчик ссылки на внешний экземпляр для включения и разбора других
документов, а также то, как можно обработать PI, и способ определения "trust/доверия" PI, содержащим код.
XML-документы, которые могут использоваться для этого примера, находятся ниже этого примера (xmltest.xml и
xmltest2.xml.)
Пример 3. Внешний экземпляр
<?php
$file = "xmltest.xml";
function trustedFile($file) {
// доверять только локальным файлам, владельцем которых являетесь вы
if (!eregi("^([a-z]+)://", $file)
&& fileowner($file) == getmyuid()) {
return true;
}
return false;
}
function startElement($parser, $name, $attribs) {
print "<<font color="#0000cc">$name</font>";
if (sizeof($attribs)) {
while (list($k, $v) = each($attribs)) {
print " <font color="#009900">$k</font>="<font
color="#990000">$v</font>"";
}
}
print ">";
}
function endElement($parser, $name) {
print "</<font color="#0000cc">$name</font>>";
}
function characterData($parser, $data) {
print "<b>$data</b>";
}
function PIHandler($parser, $target, $data) {
switch (strtolower($target)) {
case "php":
global $parser_file;
// Если разбираемому документу "доверяют", мы говорим, что он
// безопасен для выполнения в нём PHP-кода. Если нет,
// отобразить этот код.
if (trustedFile($parser_file[$parser])) {
eval($data);
} else {
printf("Untrusted PHP code: <i>%s</i>",
htmlspecialchars($data));
}
break;
}
}
function defaultHandler($parser, $data) {
if (substr($data, 0, 1) == "&" && substr($data, -1, 1) == ";") {
printf(’<font color="#aa00aa">%s</font>’,
htmlspecialchars($data));
} else {
printf(’<font size="-1">%s</font>’,
htmlspecialchars($data));
}
}
function externalEntityRefHandler($parser, $openEntityNames, $base, $systemId,
$publicId) {
if ($systemId) {
if (!list($parser, $fp) = new_xml_parser($systemId)) {
printf("Could not open entity %s at %s
", $openEntityNames,
$systemId);
return false;
}
while ($data = fread($fp, 4096)) {
if (!xml_parse($parser, $data, feof($fp))) {
printf("XML error: %s at line %d while parsing entity %s
",
xml_error_string(xml_get_error_code($parser)),
xml_get_current_line_number($parser), $openEntityNames);
xml_parser_free($parser);
return false;
}
}
xml_parser_free($parser);
return true;
}
return false;
}
function new_xml_parser($file) {
global $parser_file;
$xml_parser = xml_parser_create();
xml_parser_set_option($xml_parser, XML_OPTION_CASE_FOLDING, 1);
xml_set_element_handler($xml_parser, "startElement", "endElement");
xml_set_character_data_handler($xml_parser, "characterData");
xml_set_processing_instruction_handler($xml_parser, "PIHandler");
xml_set_default_handler($xml_parser, "defaultHandler");
xml_set_external_entity_ref_handler($xml_parser, "externalEntityRefHandler");
if (!($fp = @fopen($file, "r"))) {
return false;
}
if (!is_array($parser_file)) {
settype($parser_file, "array");
}
$parser_file[$xml_parser] = $file;
return array($xml_parser, $fp);
}
if (!(list($xml_parser, $fp) = new_xml_parser($file))) {
die("could not open XML input");
}
print "<pre>";
while ($data = fread($fp, 4096)) {
if (!xml_parse($xml_parser, $data, feof($fp))) {
die(sprintf("XML error: %s at line %d
",
xml_error_string(xml_get_error_code($xml_parser)),
xml_get_current_line_number($xml_parser)));
}
}
print "</pre>";
print "parse complete
";
xml_parser_free($xml_parser);
?>
Пример 4. xmltest.xml
<?xml version=’1.0’?>
<!DOCTYPE chapter SYSTEM "/just/a/test.dtd" [
<!ENTITY plainEntity "FOO entity">
<!ENTITY systemEntity SYSTEM "xmltest2.xml">
]>
<chapter>
<TITLE>Title &plainEntity;</TITLE>
<para>
<informaltable>
<tgroup cols="3">
<tbody>
<row><entry>a1</entry><entry morerows="1">b1</entry><entry>c1</entry></row>
<row><entry>a2</entry><entry>c2</entry></row>
<row><entry>a3</entry><entry>b3</entry><entry>c3</entry></row>
</tbody>
</tgroup>
</informaltable>
</para>
&systemEntity;
<section id="about">
<title>About this Document</title>
<para>
<!-- это комментарий -->
<?php print ’Hi! This is PHP version ’.phpversion(); ?>
</para>
</section>
</chapter>
Следующий файл включается в xmltest.xml:
Пример 5. xmltest2.xml
<?xml version="1.0"?>
<!DOCTYPE foo [
<!ENTITY testEnt "test entity">
]>
<foo>
<element attrib="value"/>
&testEnt;
<?php print "This is some more PHP code being executed."; ?>
</foo>
Содержание
utf8_decode - конвертирует строку с символами набора ISO-8859-1, кодированными в UTF-8,
в однобайтные символы ISO-8859-1