четверг, 20 октября 2011 г.

CodeIgniter и генерация XML

Я использую CodeIgniter Views не только для генерации обычных страниц, но и для карты сайта (XML sitemap) и фида в формате Atom. Встроенный парсер шаблонов не использую: он очень уж простенький - поддерживает только циклы и переменные, иногда этого не хватает. Использовать какую-то внешнюю систему вроде Smarty не хочу, чтобы не усложнять и не замедлять систему. Поэтому просто делаю во Views PHP-вставки, использовуя Alternate PHP Syntax.

С обычными HTML-страницами всё в порядке, а вот при попытке генерации XML вижу такую ошибку:

Parse error: syntax error, unexpected T_STRING in C:\MySite\application\views\sitemap.php on line 1

Проблема вот в этой строчке:
<?xml version="1.0" encoding="utf-8" ?>

Дело в том, что <? ... ?> - это короткие PHP-теги, которые могут использоваться вместо <?php ... ?>. Т.е. PHP думает, что xml version="1.0" encoding="utf-8" - это PHP-код, и пытается его запустить.

Решение - заменить первую строчку на вот это:
<?php echo '<' . '?' ?>xml version="1.0" encoding="UTF-8"<?php echo '?' . '>' ?>

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

Другой вариант - передавать во View в качестве переменных строки <? и ?> (либо вообще первую строку целиком). Шаблон будет выглядеть красивее, но зато придется немного засорить контроллер...

5 комментариев:

Igor Korkhov комментирует...

А в чем замес, так сказать? Уж если ты уродуешь XML declaration, чтобы "обмануть PHP", то не лучше ли ее (декларацию; не знаю, как по-русски правильно) просто выкинуть? Она, согласна спецификации, опциональна. А так ты делаешь XML невалидным, да еще и совершаешь лишние телодвижения.

Valik комментирует...

Наверное, я непонятно написал. Я меняю это в шаблоне будущего файла XML, а не в каком-то XML-файле. Шаблон сам по себе - это PHP-файл. Конечно, он не является валидным XML. Вот пример для генерации XML sitemap:

<?php echo '<' . '?' ?>xml version="1.0" encoding="UTF-8"<?php echo '?' . '>' ?>

<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<?php foreach ($urlset as $url):?>
<url>
<loc><?=$url->loc?></loc>
<lastmod><?=$url->lastmod?></lastmod>
</url><?php endforeach;?>

</urlset>

А то, что декларация необязательна, я, честно говоря, не знал. Ну, т.е. я знал, что и без неё иногда работает, но думал, что это нарушение стандарта.

Igor Korkhov комментирует...

Насчет "необязательна" я, наверное, погорячился. Спецификация про нее говорит "SHOULD contain", а это значит "that there may exist valid reasons in particular circumstances to ignore a particular item". То есть как бы и необязательна, но лучше, чтобы была.
А что, правда парсер PHP такой тупой, что не понимает строку ' ?> и приходится городить нечитаемую конкатенацию?

Igor Korkhov комментирует...

А, ну про то, что в Блоггере в комментарий нельзя никаким образом вставить что-то отдаленно похожее на HTML тэг, я забыл. Мой вопрос про парсер был в том, почему нельзя написать одной строкой echo 'бла-бла', где бла-бла и есть декларация сразу целиком.

Valik комментирует...

Попробовал - нет, так не получается. Даже если в настройках PHP запретить short tags (чтобы решить вопрос с открывающим тэгом, который может быть как <?php , так и просто <?), то всё равно остается проблема с закрывающим.

Т.е. в принципе можно обойтись только одно конкатенацией вместо двух, но только если ты согласен не использовать short tages (а это может сделать шаблон менее читабельным).

Ratings by outbrain