Статьи

Сгибание XML к вашей воле

Если вы когда-либо работали с API-интерфейсами Twitter или Facebook, просматривали RSS-каналы с веб-сайта или использовали какие-либо вызовы RPC, вы, несомненно, испытали работу с XML. Расширяемый язык разметки (XML) — это большой строительный блок современной сети, в котором разрабатываются сотни языков на основе XML, включая XHTML, ATOM и SOAP. Мне самому приходится работать с несколькими сторонними системами для отправки и получения данных, и для всех них предпочтительным методом является XML.

Знание того, как обрабатывать данные XML, является сегодня важнейшим навыком программирования, и, к счастью, PHP предлагает несколько способов чтения, фильтрации и даже генерации XML. В этой статье я объясню, что именно представляет собой XML, на случай, если у вас еще не было никакого опыта работы с ним, а затем углублюсь в несколько способов, которыми вы можете использовать PHP, чтобы согнуть XML по своей воле.

Что делает XML?

Краткий ответ на вопрос «Что делает XML?» — ничто. Это ничего не делает вообще. XML — это просто язык разметки, похожий на HTML. В то время как HTML был разработан для отображения данных, XML был разработан для обеспечения структурированного способа транспортировки и хранения данных.

Давайте рассмотрим простой пример XML, который содержит информацию о конкретных спортивных командах:

<?xml version="1.0" encoding="UTF-8" ?> <roster> <team> <name>Bengals</name> <division>AFC North</division> <colors>Black and Orange</colors> <stadium location="Cincinnati">Paul Brown Stadium</stadium> <coach>Marvin Lewis</coach> </team> <team> <name>Titans</name> <division>AFC South</division> <colors>Blue and White</colors> <stadium location="Tennessee">LP Field</stadium> <coach>Mike Munchak</coach> </team> </roster> 

Как видно из примера, XML читается человеком и информативен. В отличие от HTML, XML не имеет предопределенных тегов, что позволяет вам изобретать свои собственные. Любой, будь то программист или нет, может взглянуть на этот пример и понять данные. Программное обеспечение, которое вы создаете, имеет задачу писать или анализировать информацию из XML-документа.

Обмен информацией между различными платформами, базами данных и языками программирования может быть разочаровывающим усилием, но поскольку XML представляет собой простой текстовый файл, он позволяет вашим данным быть независимыми от используемого программного обеспечения. Поскольку XML является настолько распространенным стандартом, он также дает вам свободу разработки приложения, не беспокоясь о несовместимости на другом конце.

Если вы все еще немного сомневаетесь в XML и его месте в веб-разработке, взгляните на это великолепное введение в XML, «Действительно, действительно, действительно хорошее введение в XML» .

Типы парсеров XML

Существует два основных типа парсеров XML: парсеры на основе дерева и парсеры на основе событий (иногда их называют потоковыми парсерами). Парсеры на основе дерева считывают весь XML-документ в память, структурируют данные в древовидный формат и предоставляют доступ к элементам дерева. С другой стороны, основанные на событиях парсеры читают в XML и вызывают событие каждый раз, когда достигают нового начального или конечного тега. Это позволяет вам применять функцию, относящуюся к вашему приложению, когда происходит событие для определенного элемента. Поскольку вы не храните весь XML-документ в памяти, анализаторы на основе событий, как правило, работают быстрее и требуют меньше ресурсов, чем основанные на дереве. Парсеры на основе дерева, как правило, проще в использовании и требуют меньше кода.

В PHP 5 есть множество инструментов для работы с XML, включая синтаксический анализатор XML (он же SAX или Expat Parser), DOM, SimpleXML, XMLReader, XMLWriter и расширения XSL. Для краткости я рассмотрю только два наиболее широко используемых синтаксических анализатора, расширения XML Parser и SimpleXML, которые по совпадению относятся к каждому парсеру каждого типа.

Использование расширения парсера XML

Первый пример, который я покажу вам, включает использование расширения XML Parser, анализатора на основе событий. Для начала давайте используем тот же XML-пример из предыдущего и проанализируем его с расширением. Представьте, что вам было дано задание разобрать XML в простой список для отображения на веб-странице. Создайте файл nfl.xml с примером XML в качестве его содержимого.

Создайте другой файл с именем xmlParserExample.php со следующим кодом:

 <?php $xmlFile = "nfl.xml"; $parser = xml_parser_create(); xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, false); xml_set_element_handler($parser, array(NFLParser, "openTag"), array(NFLParser, "closeTag")); xml_set_character_data_handler($parser, array(NFLParser, "characterData")); $fp = fopen($xmlFile, "r"); while ($data = fread($fp, 4096)) { xml_parse($parser, $data, feof($fp)) or die (sprintf("XML Error: %s at line %d", xml_error_string(xml_get_error_code($parser)), xml_get_current_line_number($parser))); } xml_parser_free($parser); class NFLParser { protected static $element; protected static $attrs; public static function openTag($parser, $elementName, $elementAttrs) { self::$element = $elementName; self::$attrs = $elementAttrs; switch($elementName) { case "team": echo "<ul>"; break; case "division": echo "<li>Division: "; break; case "name": echo "<li>Team Name: "; break; case "colors": echo "<li>Team Colors: "; break; case "stadium": echo "<li>Stadium: "; break; case "coach": echo "<li>Head Coach: "; } } public static function closeTag($parser, $elementName) { self::$element = null; self::$attrs = null; if ($elementName == "team") { echo "</ul>"; } elseif($elementName != "roster") { echo "</li>"; } } public static function characterData($parser, $data) { echo $data; if (self::$element == "stadium") { echo " (" . self::$attrs["location"] . ")"; } } } 

Функция xml_parser_create() создает новый обработчик синтаксического анализатора XML, который используется во всем коде. Следующая функция, xml_parser_set_option() , используется для установки параметров парсера. В этом случае XML_OPTION_CASE_FOLDING параметра XML_OPTION_CASE_FOLDING установлено значение false (поскольку по умолчанию установлено значение true). Свертывание регистра — это процесс, применяемый к последовательности символов, в которой все они преобразуются в верхний регистр. Установив для этого параметра значение true, я могу сохранить чувствительность к регистру тегов в точности так, как они отображаются в файле XML.

Функция xml_set_element_handler() устанавливает обработчики начального и конечного элементов парсера. Эта функция принимает три параметра: первый параметр — это ссылка на синтаксический анализатор, второй параметр — это функция обратного вызова, которая будет обрабатывать открывающие теги (статический openTag() класса NFLParser в примере), а третий параметр — это обратный вызов, который будет обрабатывать закрывающие теги (метод closeTag() ).

PHP передает три параметра в openTag() : анализатор, имя элемента, для которого вызывается этот обработчик, и ассоциативный массив любых атрибутов для элемента. Для closeTag() предоставляются два параметра: анализатор и имя элемента.

Функция xml_set_character_data_handler() определяет функцию, которая будет обрабатывать символьные данные для элемента. Функция принимает два параметра: анализатор и имя функции обратного вызова, которая в этом примере является статическим методом characterData() . Методу characterData() передаются два параметра: синтаксический анализатор и символьные данные из элемента.

Оставшаяся часть кода в этом примере считывается в XML-файл и вызывает xml_parse() которая запускает процесс синтаксического анализа. xml_parse() принимает три параметра: синтаксический анализатор, блок данных для анализа и логический параметр, который указывает, является ли это последним фрагментом данных.

Последняя xml_parser_free() функция — xml_parser_free() ; Как и в случае с обработкой файлов, всегда полезно освободить дескриптор ссылки, когда вы закончите.

Я решил инкапсулировать методы в классе NFLParser чтобы можно было отслеживать текущий элемент и атрибуты, анализируемые в $element и $attrs не загрязняя глобальное пространство имен, и делать их доступными для метода characterData() .

Выполните ваш скрипт, и у вас должен получиться красивый список HTML всех данных из XML.

 <ul> <li>Team Name: Titans</li> <li>Team Colors: Blue and White</li> <li>Stadium: LP Field (Nashville)</li> <li>Head Coach: Mike Munchak</li> </ul> <ul> <li>Team Name: Bengals</li> <li>Team Colors: Black and Orange</li> <li>Stadium: Paul Brown Stadium (Cincinnati)</li> <li>Head Coach: Marvin Lewis</li> </ul> 

Что ж, это было не так уж плохо интерпретировать XML с помощью PHP с использованием анализатора событий, но что, если бы существовал еще более простой способ нарезки XML, более простой, если хотите, способ?

Использование SimpleXML

Расширение SimpleXML было введено в PHP 5 и отнимает много утомительных манипуляций с XML. SimpleXML — это объектно-ориентированный синтаксический анализатор, основанный на дереве, поэтому это более медленный и более ресурсоемкий способ анализа XML, но любая потеря скорости при использовании этого расширения будет надолго забыта, как только вы увидите, насколько «простым» оно действительно является.

Создайте файл с именем simpleXMLExample.php и введите следующий код:

 <?php $xmlFile = "nfl.xml"; $xml = simplexml_load_file($xmlFile); foreach($xml->team as $element){ $attr = $element->stadium->attributes(); $location = $attr->location; echo "<ul>n"; echo " <li>Division:" . $element->division . "</li>n"; echo " <li>Team Name:" . $element->name . "</li>n"; echo " <li>Team Colors:" . $element->color . "</li>n"; echo " <li>Stadium:" . $element->stadium ." (" . $location. ")</li>n"; echo " <li>Coach" . $element->coach . "</li>n"; echo "</ul>n"; } 

Выполнение этого скрипта приведет к тому же результату, но без необходимости писать большую часть кода синтаксического анализа.

Вам может быть интересно, почему вы используете расширение, такое как XML Parser, если SimpleXML настолько… ну, просто? Я сравниваю этот вопрос со строителем, который идет на работу с молотком в поясе. Конечно, он получит, забивая гвозди на некоторое время, но что в конечном итоге он столкнется с винтом. Даже если один инструмент может быть проще в использовании, он не делает его идеальным выбором для любой ситуации.

Резюме

В этой статье вы немного узнали о XML и о том, как он используется в Интернете. Что еще более важно, вы узнали о двух основных типах синтаксических анализаторов XML: синтаксических анализаторах на основе дерева и на основе событий. PHP предлагает несколько различных расширений для разбора XML, двумя из которых являются XML Parser и SimpleXML. Каждый предлагает компромиссы с производительностью, простотой использования и объемом кода, который должен написать программист. Надеемся, что использование обоих расширений поможет вам уверенно выбрать лучший подход в следующий раз, когда вам понадобится XML.

Изображение с помощью Ken Durden / Shutterstock