Гостиница «Которосль» в Ярославле
Номер категории «Люкс» в гостинице «Которосль» — это, ребята, сидячая ванна, механические замки, шумный холодильник «Смоленск» (этакий отбойный молоток в ночи), отсутствие халата, зубной щётки, мусорки, сейфа и интернета. Правда мебель чистенькая и новая, хотя и тошнотворная, но я не понимаю почему это называется «Люкс». Чего тут «люксового»?
Добавлено на следующий день: вот так выглядит спальня в номере, обратите внимание на оригинальную конструкцию лампы. Нет, это не реализация идей Тесла по беспроводной передачи электричества, это просто провод обрезан.

Кстати, на конференции ADD, где я сейчас нахожусь, Windows 7 отказалась подключаться к интернету, пришлось на телефоне («Андроид» подключился без проблема и сразу) посмотреть выданный
PHP4 без XML-парсера
Мне тут по работе пришлось решить странную, по нынешним временам задачу — принимать XML в программе на PHP4.3+, где никакого парсера XML может не оказаться. Таковы реалии продукта и среды, где он будет использоваться (это код внешнего проекта). Поэтому мне пришлось написать небольшой парсер, который, правда, расcчитывает, что XML будет
В качестве иллюстрации я использую в коде крайне простую функцию, которая не строит дерево, а просто собирает вызовы в массив, но понятно, что собрать дерево тоже ничего не стоит.Дальше
<?
// Very Simple XML SAX Parser by Evgeny Stepanischev
// /
class VerySimple_XMLParser
{
var $saxCallback;
function VerySimple_XMLParser($saxCallback)
{
$this->saxCallback = $saxCallback;
}
function parse($xml)
{
if (preg_match_all('#<![CDATA[.*?]]>|</?[^>]*>|[^<]+#us', $xml, $matches)) {
foreach ($matches[0] as $match) {
$this->parseThis($match);
}
}
}
function parseThis($match)
{
$calls = array(
'<!--' => 'COMMENT',
'<?' => 'PI',
'<![CDATA[' => 'CDATA',
'<!' => 'DTD',
'</' => 'TAGCLOSE',
'<' => 'TAGOPEN',
);
foreach ($calls as $need => $type) {
if (strpos($match, $need) === 0) {
return $this->parseByType($type, $match);
}
}
return $this->parseByType('OTHER', $match);
}
function parseByType($type, $text)
{
if ($type == 'COMMENT') {
return $this->addChunk($type, substr($text, 4, -3));
}
if ($type == 'CDATA') {
return $this->addChunk('TEXT', substr($text, 9, -3));
}
if ($type == 'OTHER') {
return $this->addChunk('TEXT', $text);
}
if ($type == 'TAGCLOSE') {
$end = strcspn($text, ' >');
return $this->addChunk('TAGCLOSE', substr($text, 2, $end - 2));
}
if ($type == 'TAGOPEN') {
$this->addChunk('TAGOPEN', $this->parseTag($text));
if (substr($text, -2) == '/>') {
$end = strcspn($text, ' >');
return $this->addChunk('TAGCLOSE', substr($text, 1, $end - 2));
}
}
return '';
}
function parseTag($text)
{
$end = strcspn($text, ' />');
$name = substr($text, 1, $end - 1);
return array($name, $this->parseTagAttributes(substr($text, $end)));
}
function parseTagAttributes($text)
{
$nameStart = '(?:[A-Za-z_:]|[^\x00-\x7F])';
$nameChar = '(?:[A-Za-z0-9_:\.-]|[^\x00-\x7F])';
$attrValue = '(?:\'[^\']*\'|"[^"]*")';
if (preg_match_all("/{$nameStart}{$nameChar}*=$attrValue/us", $text, $matches)) {
return $this->parseAttributes($matches[0]);
}
return array();
}
function parseAttributes($rawAttributes)
{
$attributes = array();
foreach ($rawAttributes as $rawAttr) {
list($name, $value) = explode('=', $rawAttr, 2);
if ($value[0] == '"' || $value[0] == "'") {
$value = substr($value, 1, -1);
}
$attributes[$name] = $value;
}
return $attributes;
}
function addChunk($type, $arg)
{
call_user_func($this->saxCallback, $type, $arg);
}
}
// Пример использования
$xml =<<<XML
<!-- комментарий -->
<?xml version="1.0"?>
<root attribute="a.a" v="a">
<v><![CDATA[data]]></v>
<v>data</v>
<v/>
</root>
XML;
// Понятно, что можно написать класс и передать в качестве
// callback в парсер метод объекта, но я для простоты, как пример,
// написал очень простую функцию
function VerySimple_XMLParser_Collector()
{
static $tree = array();
if (func_num_args() == 2) {
$tree[] = func_get_args();
} else {
return $tree;
}
}
$sax = &new VerySimple_XMLParser('VerySimple_XMLParser_Collector');
$sax->parse($xml);
echo '<plaintext>';
var_dump(VerySimple_XMLParser_Collector());