Генерация XML в PHP

14 июля 2008

Рассматривая примеры генерации XML-выгрузок от различных украинских маркетов (не буду никого смущать прямыми ссылками), удивлен тем, что многие используют обыкновенную шаблонную методику, вроде:

<item id=”<?=$o->productID?>” top=”0”>
	<name><?=to_xml($o->name)?></name>
	<price><?=$o->price?></price>
	<categoryId><?=$o->categoryID?></categoryId>
	<description><?=to_xml($o->description)?></description>
	<url><?=to_xml(”http://myshop.kiev.ua/index.php?productID=”.$o->productID)?></url>
	<image><?=to_xml(”http://myshop.kiev.ua/pictures/”.$o->image)?></image>
</item>

Я уже молчу о том, что в данном конкретном примере присутствуют short_open_tags.
Но почему не использовать встроенные в PHP 5 DOM-классы? Это дает нам такие преимущества (навскидку):

  • гарантированная валидность результата (и соответствие DTD, если его указать)
  • автоматическое форматирование ($dom -> formatOutput = true;)
  • автоматическое преобразование кодировки – достаточно указать нужную в заголовке файла.

Посмотрим на генерацию того же фрагмента XML средствами DomDocument:

$item = $dom_items -> appendChild( $dom->createElement('item'));
$item -> setAttribute('id', $o->productID);
$item -> setAttribute('top', '0');

$item -> appendChild( $dom->createElement('price', $record['price']));
$item -> appendChild( $dom->createElement('categoryId', $o->categoryID));
$item -> appendChild( $dom->createElement('name',htmlspecialchars($o->name)));
$item -> appendChild( $dom->createElement('description',
	htmlspecialchars($o->description)));
$item -> appendChild( $dom->createElement('url',
	htmlspecialchars("http://myshop.kiev.ua/index.php?productID=".$o->productID)));
$item -> appendChild( $dom->createElement('image', 
	htmlspecialchars("http://myshop.kiev.ua/pictures/".$o->image)));

Разве этот код не понятнее и структурнее, чем tag soup из первого примера? Да, писать придется немного больше, зато ты никаким образом не отдашь в XML неэскейпленные символы, незакрытые теги и прочий мусор.

Немного теории

Для начала все, что надо знать – это пять функций. Почитай их описание в PHP Manual:

  • $dom = DOMDocument::loadXML('<?xml version="1.0" encoding="utf-8"?><root_node/>'); – создает документ вместе с корневым элементом $dom -> documentElement
  • DOMElement::setAttribute('name', $value) – устанавливает атрибут
  • DOMElement::appendChild( $dom->createElement('name', [$text]) ) – создает в документе элемент <name>text</name> и добавляет в другой элемент
  • $dom->saveXML() – отдает всю эту красоту в виде строки

Все, дальше курим маны и больше никогда, никогда, никогда не выводим XML шаблонами.



Три комментария. Напиши еще один
  1. 77155c3952294adc6d15847fdb26b040 # 14 июля 2008 Alex написал:

    Если надо только сгенерить XML, то ИМХО правильнее будет использовать XMLWriter, т.к. генерация Dom дерева жрет больше ресурсов.

  2. 3c53262cdb212077dd9c4320cd0b0e86 # 14 июля 2008 Vadim Voituk (voituk.kiev.ua) написал:

    +1 к комментарию Alex.

    Не смотря на минусы (кстати у него есть и плюсы) первого предложенного метода, второй тоже далек от идела удобства.
    Во втором методе теряется главное – связь между структурой кода и структурой данных, что я воспринимаю как недальновидность разработчика (через 2 года поди разбери структуру этого XML глядя на код)

    Лично меня уже тошнит от этих w3c-шных createElement/setAttribute/appendChild.

  3. 777894ea5153122bfa6b83f5bbf23622 # 14 июля 2008 Леонид Шевцов (автор) написал:

    Структуру сохранить не сложно, если разделять генерацию всего документа на отдельные методы.

    Касательно разбирания структуры – предлагаю сопровождать любой генерирующий XML код либо DTD, либо RelaxNG-схемой – как минимум для юнит-тестов.

(нужна разметка?)

  • **жирный**
  • > цитата

отменить