Существует множество методов чтения и записи XML с помощью PHP. В этой статье представлены три метода чтения XML: использование библиотеки DOM, использование анализатора SAX и использование регулярных выражений. Также рассматривается написание XML с использованием текстовых шаблонов DOM и PHP.
Чтение и написание расширяемого языка разметки (XML) на PHP может показаться немного пугающим. На самом деле XML и все связанные с ним технологии могут быть страшными, но чтение и запись XML на PHP не обязательно должны быть страшной задачей. Во-первых, вам нужно немного узнать об XML — что это такое и что с ним можно делать. Затем вам нужно научиться читать и писать XML на PHP, и есть много способов сделать это.
В этой статье представлено краткое введение в XML, а затем объясняется, как читать и писать XML с помощью PHP.
Что такое XML?
XML — это формат хранения данных. Он не определяет, какие данные сохраняются, а также не определяет формат данных. XML просто определяет теги и атрибуты этих тегов. Правильно сформированная XML-разметка выглядит следующим образом:
<имя>Джек Херрингтон</имя>
Этот тег <name> содержит текст: Джек Херрингтон.
XML-разметка без текста выглядит так:
<PowerUp/>
Существует несколько способов написать что-либо в XML. Например, этот тег формирует тот же вывод, что и предыдущий тег:
<PowerUp></powerUp>
Вы также можете добавлять атрибуты в теги XML. Например, этот тег <name> содержит атрибуты first и last:
<имя first="Джек" Last="Херрингтон" />
Специальные символы также могут быть закодированы в XML. Например, символ & можно закодировать следующим образом:
&
XML-файл, содержащий теги и атрибуты, имеет правильный формат, если он отформатирован, как в примере, что означает, что теги симметричны, а символы закодированы правильно. Листинг 1 представляет собой пример правильно сформированного XML.
Листинг 1. Пример списка книг в формате XML
<книги>
<книга>
<автор>Джек Херрингтон</автор>
<title>PHP-хаки</title>
<издатель>О'Рейли</издатель>
</книга>
<книга>
<автор>Джек Херрингтон</автор>
<title>Хаки для подкастинга</title>
<издатель>О'Рейли</издатель>
</книга>
</книги>
|
XML в листинге 1 содержит список книг. Родительский тег <books> содержит набор тегов <book>, каждый из которых содержит теги <author>, <title> и <publisher>.
XML-документ является корректным, если его структура и содержимое разметки проверены внешним файлом схемы. Файлы схемы могут быть указаны в разных форматах. Для этой статьи все, что нужно, — это правильно сформированный XML.
Если вы думаете, что XML очень похож на язык гипертекстовой разметки (HTML), вы правы. XML и HTML являются языками разметки и имеют много общего. Однако важно отметить, что, хотя XML-документ может быть правильно сформированным HTML, не все HTML-документы являются правильно сформированным XML. Тег новой строки (br) — хороший пример разницы между XML и HTML. Этот тег новой строки представляет собой правильно сформированный HTML, но не корректный XML:
<p>Это абзац<br>
С переносом строки</p>
Этот тег новой строки представляет собой правильно сформированный XML и HTML:
<p>Это абзац<br />
С переносом строки</p>
Если вы хотите писать HTML как правильно сформированный XML, следуйте стандарту расширяемого языка разметки гипертекста (XHTML) комитета W3C (см. Ресурсы ). Все современные браузеры могут отображать XHTML. Кроме того, вы можете использовать инструменты XML для чтения XHTML и поиска данных в документе, что намного проще, чем анализ HTML.
Чтение XML с использованием библиотеки DOM
Самый простой способ прочитать правильно сформированные XML-файлы — использовать библиотеку объектной модели документа (DOM), скомпилированную в некоторые установки PHP. Библиотека DOM считывает весь XML-документ в память и представляет его в виде дерева узлов, как показано на рисунке 1.
Рисунок 1. Дерево XML DOM для книги XML
Узел книг в верхней части дерева имеет два дочерних тега книг. В каждой книге есть несколько узлов: автор, издатель и название. Каждый из узлов автора, издателя и заголовка имеет текстовые дочерние узлы, содержащие текст.
Код, который читает XML-файл книги и отображает его содержимое с помощью DOM, показан в листинге 2.
Листинг 2. Чтение XML книги с использованием DOM
<?php
$doc = новый DOMDocument();
$doc->load('books.xml');
$books = $doc->getElementsByTagName("книга");
foreach($books как $book)
{
$authors = $book->getElementsByTagName("автор");
$author = $authors->item(0)->nodeValue;
$publishers = $book->getElementsByTagName("издатель");
$publisher = $publishers->item(0)->nodeValue;
$titles = $book->getElementsByTagName("title");
$title = $titles->item(0)->nodeValue;
echo "$title - $author - $publishern";
}
?>
|
Сценарий сначала создает новый объект DOMdocument и загружает XML-файл книги в этот объект с помощью метода загрузки. После этого скрипт использует метод getElementsByName для получения списка всех элементов с указанным именем.
В цикле узла книги сценарий использует метод getElementsByName для получения nodeValue тегов автора, издателя и заголовка. nodeValue — это текст в узле. Затем сценарий отображает эти значения.
Вы можете запускать PHP-скрипты в командной строке следующим образом:
%phpe1.php
PHP-хаки - Джек Херрингтон - О'Рейли
Советы по подкастингу - Джек Херрингтон - О'Рейли
%
Как видите, каждый книжный блок выводит одну строку. Это хорошее начало. Но что, если у вас нет доступа к библиотеке XML DOM?
Чтение XML с помощью парсера SAX
Другой способ чтения XML — использование синтаксического анализатора XML Simple API (SAX). Большинство установок PHP включают парсер SAX. Анализатор SAX работает по модели обратного вызова. Каждый раз, когда тег открывается или закрывается, или каждый раз, когда анализатор видит текст, пользовательская функция вызывается обратно с информацией об узле или тексте.
Преимущество парсера SAX в том, что он действительно легкий. Парсер не хранит содержимое в памяти в течение длительного времени, поэтому его можно использовать для очень больших файлов. Недостатком является то, что написание обратных вызовов парсера SAX очень громоздко. В листинге 3 показан код, использующий SAX для чтения XML-файла книги и отображения его содержимого.
Листинг 3. Чтение XML книги с помощью парсера SAX
<?php
$g_books = массив();
$g_elem = ноль;
функция startElement($parser, $name, $attrs)
{
глобальные $g_books, $g_elem;
if ( $name == 'BOOK' ) $g_books []= array();
$g_elem = $имя;
}
функция endElement($parser, $name)
{
глобальный $g_elem;
$g_elem = ноль;
}
функция textData($parser, $text)
{
глобальные $g_books, $g_elem;
if ( $g_elem == 'АВТОР' ||
$g_elem == 'ИЗДАТЕЛЬ' ||
$g_elem == 'НАЗВАНИЕ')
{
$g_books[ count($g_books) - 1 ][ $g_elem ] = $text;
}
}
$parser = xml_parser_create();
xml_set_element_handler($parser, "startElement", "endElement");
xml_set_character_data_handler($parser, "textData");
$f = fopen('books.xml', 'r');
while($data = fread($f, 4096))
{
xml_parse($парсер, $данные);
}
xml_parser_free($parser);
foreach($g_books как $book)
{
echo $book['TITLE']." - ".$book['AUTHOR']." - ";
echo $book['ПУБЛИШЕР']."n";
}
?>
|
Сначала скрипт устанавливает массив g_books, который хранит в памяти все книги и информацию о книгах, а переменная g_elem содержит имя тега, который в данный момент обрабатывается сценарием. Затем сценарий определяет функцию обратного вызова. В этом примере функциями обратного вызова являются startElement, endElement и textData. При открытии и закрытии метки вызывайте функции startElement и endElement соответственно. TextData вызывается для текста между открывающим и закрывающим тегами.
В этом примере тег startElement ищет тег book, чтобы начать новый элемент в массиве книг. Затем функция textData просматривает текущий элемент, чтобы определить, является ли он тегом издателя, заголовка или автора. Если да, функция помещает текущий текст в текущую книгу.
Чтобы продолжить синтаксический анализ, скрипт создает синтаксический анализатор с помощью функции xml_parser_create. Затем установите дескриптор обратного вызова. После этого скрипт считывает файл и отправляет его фрагменты анализатору. После прочтения файла функция xml_parser_free удаляет парсер. В конце скрипта выводится содержимое массива g_books.
Как видите, это гораздо сложнее, чем писать тот же функционал в DOM. Что делать, если нет библиотеки DOM и библиотеки SAX? Есть ли альтернативы?
Анализ XML с помощью регулярных выражений
Я уверен, что некоторые инженеры будут критиковать меня за упоминание этого метода, но XML можно анализировать с помощью регулярных выражений. В листинге 4 показан пример использования функции preg_ для чтения файла книги.
Листинг 4. Чтение XML с помощью регулярных выражений
<?php
$xml = "";
$f = fopen('books.xml', 'r');
while($data = fread($f, 4096)) {$xml .= $data }
fзакрыть ($ е);
preg_match_all( "/<book>(.*?)</book>/s",
$xml, $bookblocks);
foreach($bookblocks[1] как $block)
{
preg_match_all( "/<автор>(.*?)</author>/",
$блок, $автор);
preg_match_all( "/<title>(.*?)</title>/",
$блок, $заголовок);
preg_match_all( "/<publisher>(.*?)</publisher>/",
$блок, $издатель);
echo( $title[1][0]." - ".$author[1][0]." - ".
$publisher[1][0]."n" );
}
?>
|
Обратите внимание, насколько короткий этот код. Первоначально он считывает файл в большую строку. Затем используйте функцию регулярного выражения для чтения каждого элемента книги. Наконец, используйте цикл foreach, чтобы просмотреть каждый блок книги и извлечь автора, название и издателя.
Итак, где же недостатки? Проблема с использованием кода регулярных выражений для чтения XML заключается в том, что сначала не проверяется правильность формата XML. Это означает, что невозможно узнать, правильно ли сформирован XML, перед его чтением. Кроме того, некоторые правильно сформированные XML-коды могут не соответствовать регулярному выражению, поэтому их необходимо изменить позже.
Я никогда не рекомендую использовать регулярные выражения для чтения XML, но иногда это лучший способ обеспечить совместимость, поскольку функции регулярных выражений всегда доступны. Не используйте регулярные выражения для чтения XML непосредственно от пользователя, поскольку вы не можете контролировать формат или структуру такого XML. Вы всегда должны использовать библиотеку DOM или анализатор SAX для чтения XML от пользователя. Написание XML с использованием DOM
Чтение XML — это только часть уравнения. Как написать XML? Лучший способ написать XML — использовать DOM. В листинге 5 показано, как DOM создает XML-файл книги.
Листинг 5. Написание XML книги с использованием DOM
<?php
$books = массив();
$books [] = массив(
'title' => 'PHP-хаки',
'author' => 'Джек Херрингтон',
'издатель' => "О'Рейли"
);
$books [] = массив(
'title' => 'Хаки для подкастов',
'author' => 'Джек Херрингтон',
'издатель' => "О'Рейли"
);
$doc = новый DOMDocument();
$doc->formatOutput = true;
$r = $doc->createElement("книги");
$doc->appendChild($r);
foreach($books как $book)
{
$b = $doc->createElement("книга");
$author = $doc->createElement("автор");
$author->appendChild(
$doc->createTextNode($book['author'])
);
$b->appendChild($author);
$title = $doc->createElement("title");
$title->appendChild(
$doc->createTextNode($book['title'])
);
$b->appendChild($title);
$publisher = $doc->createElement("издатель");
$publisher->appendChild(
$doc->createTextNode($book['publisher'])
);
$b->appendChild($publisher);
$r->appendChild($b);
}
эхо $doc->saveXML();
?>
|
В верхней части скрипта массив Books загружается с примерами книг. Эти данные могут поступать от пользователя или из базы данных.
После загрузки образцов книг сценарий создает новый DOMDocument и добавляет к нему узел корневых книг. Затем сценарий создает узлы для автора, названия и издателя каждой книги и добавляет текстовые узлы к каждому узлу. Последним шагом для каждого узла книги является повторное добавление его в корневой узел book.
В конце сценария используйте метод saveXML для вывода XML на консоль. (Вы также можете использовать метод save для создания XML-файла.) Вывод сценария показан в листинге 6.
Листинг 6. Вывод сценария сборки DOM
%phpe4.php
<?xml версия="1.0"?>
<книги>
<книга>
<автор>Джек Херрингтон</автор>
<title>PHP-хаки</title>
<издатель>О'Рейли</издатель>
</книга>
<книга>
<автор>Джек Херрингтон</автор>
<title>Хайки для подкастов</title>
<издатель>О'Рейли</издатель>
</книга>
</книги>
%
|
Настоящая ценность использования DOM заключается в том, что создаваемый им XML всегда имеет правильный формат. Но что, если вы не можете создать XML с помощью DOM?
Написание XML на PHP
Если DOM недоступен, XML можно записать с использованием текстовых шаблонов PHP. В листинге 7 показано, как PHP создает XML-файл книги.
Листинг 7. Написание книги XML на PHP
<?php
$books = массив();
$books [] = массив(
'title' => 'PHP-хаки',
'author' => 'Джек Херрингтон',
'издатель' => "О'Рейли"
);
$books [] = массив(
'title' => 'Хаки для подкастов',
'author' => 'Джек Херрингтон',
'издатель' => "О'Рейли"
);
?>
<книги>
<?php
foreach($books как $book)
{
?>
<книга>
<title><?php echo( $book['title'] ?></title>);
<автор><?php echo( $book['author'] ?>;
</автор>
<издатель><?php echo( $book['publisher'] ?>);
</издатель>
</книга>
<?php
}
?>
</книги>
|
Верхняя часть сценария аналогична сценарию DOM. В нижней части скрипта открывается тег «книги», а затем он проходит по каждой книге, создавая тег книги и все внутренние теги названия, автора и издателя.
Проблема этого подхода заключается в кодировании объектов. Чтобы гарантировать правильность кодирования сущностей, функцию htmlentities необходимо вызывать для каждого элемента, как показано в листинге 8.
Листинг 8. Кодирование сущностей с помощью функции htmlentities
<книги>
<?php
foreach($books как $book)
{
$title = htmlentities($book['title'], ENT_QUOTES);
$author = htmlentities($book['author'], ENT_QUOTES);
$publisher = htmlentities($book['publisher'], ENT_QUOTES);
?>
<книга>
<title><?php echo( $title ?></title>);
<автор><?php echo( $author ?> </автор>);
<издатель><?php echo( $publisher );
</издатель>
</книга>
<?php
}
?>
</книги>
|
Именно здесь написание XML на базовом PHP становится раздражающим. Вы думаете, что создали идеальный XML, но как только вы попытаетесь использовать данные, вы обнаружите, что некоторые элементы закодированы неправильно.
Заключение
Вокруг XML всегда много преувеличений и путаницы. Однако это не так сложно, как вы думаете, особенно на таком замечательном языке, как PHP. Как только вы поймете и правильно реализуете XML, в вашем распоряжении появится множество мощных инструментов. XPath и XSLT — два таких инструмента, которые стоит изучить.