2003-01-21T16:55:15+00:00
В связи с появлением в парсере возможности работать с внешними файлами (не на локальном сервере), появилась возможность получать и выводить информацию из внешних источников у себя на сайте.
В этом примере я рассмотрю использование внешнего XML файла с анонсами материалов, для опубликования ссылок на эти материалы у себя на сайте. Сделаю это на примере сайта php в деталях. Содержимое и структуру XML этого файла смотрите по адресу, который найдете в нижеприведённом коде.
Небольшое предостережение — если XML файл расположен на сервере с русским Apache, нужно обязательно отключить перекодировку с его помощью, иначе может возникнуть ситуация с несовпадением реальной и кодировки в XML декларации. Ну и теперь к делу, — код выглядит следующим образом:
#######
# формирование анонсов последних материалов
# с сайта php в деталях
# Блок <ul>...</ul> написал Константин Томашевич (konst@design.ru)
@phpdetails[][src;local_file;xml;list;now]
# определяем локальный файл где находится XML
$local_file[/phpdetails/last10.xml]
# проверяем локальный файл, - если его дата изменения более чем на
# день старее текущего времени, грузим его с внешнего сервера
$src[^file::stat[$local_file]]
$now[^date::now[]]
^if($src.mdate < $now-1){
# пытаемся загрузить внешний XML файл и сохранить его
# если не удается загрузка, обрабатываем исключение и ничего не делаем
^try{
$src[^file::load[text;http://detail.phpclub.net/last10.xml]]
^src.save[text;$local_file]
}{
$exception.handled(1)
}
}
# всегда создаем объект класса xdoc из XML файла на локальном диске
# разумеется он должен всегда существовать. При удачной загрузке с
# внешнего сервера, он ещё и постоянно обновляется
$xml[^xdoc::load[$local_file]]
# хэш элементов(анонсов) из файла, нужен для определения количества анонсов
$list[^xml.select[/last/item]]
<ul>
#!*!# нумерациЯ с 0 (исправлен range в if)
^for[i](0;$list-1){
#!*!# нет смысла делать еще раз selectXXX, ибо мы уже в цикле типа xsl:for-each
#!*!# более того, если не проверЯешь наличие аттрибутов, можно сократить до
#!*!# одной строки - $list == hash of xnode (/last/item)
<li>
^list.[$i].getAttribute[date]
<a href="http://detail.phpclub.net/^list.[$i].getAttribute[dir]^list.[$i].getAttribute[file].htm">
^list.[$i].getAttribute[title]
</a>
</li>
}
</ul>
Немного комментариев.
- Работа по вытягиванию информации из XML всегда ведется с локальным файлом.
- Раз в сутки проверяется дата изменения локального файла и если она более чем на сутки старее текущий производится загрузка внешнего файла.
- Здесь сделано предположение, что, внешний файл меняется раз в сутки, если это не так и файл меняется гораздо реже, стоит этот период увеличить.
Пусть вас не удивляют странные комментарии сделанные между тегами ul — первоначальный вариант кода был такой:
<ul>
^for[i](1;$list){
$date{^xml.selectString[string(/last/item[position() = $i]/@date)]}
$title{^xml.selectString[string(/last/item[position() = $i]/@title)]}
$path{^xml.selectString[string(/last/item[position() = $i]/@dir)]}
$file{^xml.selectString[string(/last/item[position() = $i]/@file)]}
<li>$date <a href="http://detail.phpclub.net/${path}${file}.htm">$title</a></li>
}
</ul>
Да, — совсем не обязательно проверять дату изменения, можно проверять и дату создания, но это не принципиально.
И в заключении — большое спасибо Константину Томашевичу, за ценные советы по работе с методами класса xnode и написанию части кода примера.