Реклама в журнале

Псевдо-XML

Источник: http://spectator.ru/

Дмитрий Смирнов

Сейчас пробую сделать что-то типа псевдо-xml. Никаких модулей у хостера не стоит, поэтому приходится разбирать все «вручную» с помощью PHP.

Нашел в Сети вот это. Простая функция, которая «…extracts the content of all tags ($tag) in string ($string). When ($mode) is 1 it returns the content as an array, otherwise as a string». То есть вы пишите $quotetext=untag ($string, "blockquote", 0) и получаете текст, который заключен в <blockquote>этот тэг</blockquote>.


function untag ($string, $tag, $mode)
{
$tmpval="";
$preg="/<".$tag.">(.*?)</".$tag.">/si";
preg_match_all ($preg,$string,$tags);
foreach ($tags[1] as $tmpcont) {
if ($mode==1){$tmpval[]=$tmpcont;}
else {$tmpval.=$tmpcont;}
}
return $tmpval;
}

Регулярные выражения рулят, но… KISS-принцип гласит: «Keep It Simple, Stupid». Очень часто можно обойтись без регулярных выражений, используя функции, которые работают быстрее. Это известная фишка — что strpos работает очень быстро и в некоторых случаях может запросто заменить некоторые регулярные выражения.

А теперь — сюрприз! Если пожертвовать «универсальностью» (например, выдачей текста в виде array’а или нечувствительностью к регистру тэгов), то можно сделать так, чтобы эта функция работала в восемь раз быстрее.

Таким вот образом —

function tags ($string, $tag)
{
$z=strpos ($string, "<".$tag.">")+strlen ($tag)+2;
$s=substr ($string, $z, strpos ($string, "</".$tag.">")-$z);
return $s;
}

Итого: 1) Можно использовать обе функции, первую — когда надо получить именно array, вторую — когда надо получить только 1-ое вхождение и вы точно знаете, в каком регистре пишутся тэги. 2) Часто можно обойтись без регулярных выражений.

Применение: для движков сайтов. Например, дату можно писать как <date>32 мартобря</date> в любом месте текста. А потом выкусывать с помощью этой функции. Получаем что и хотели — «псевдо-ХМL».

Для полноты картины добавим обработку ошибок (если ничего не найдено):


function untag ($string, $tag)
{
$z = strpos ($string, '<'.$tag.'>');
if ($z!==false) {
$z=$z+ strlen ($tag) + 2;
$z2 = strpos ($string, '</'.$tag.'>');
$s = substr ($string, $z, $z2 - $z);
return $s;
}
};

Для тех, кто в танке! В комментариях к данной заметке нашелся умник, который хочет «всего-лишь показать, что главный недостаток регулярных выражений — нежелание в них разбираться». При этом предлагает свой пример, который работает как минимум в шесть раз медленней. Что критично. Уважаемый! Главный недостаток регулярных выражений — это то, что некоторые люди, которые «разобрались» в регулярных выражениях, пихают их куда ни попадя.

Update: От читателя пришел апдейт этой функции. Теперь она может вырезать тэги с параметрами, типа <td …>…</td> и складывать содержимое одинаковых тэгов в array.

<?

// (C) Шушпанов Пётр Анатольевич
// mail: web@phystech.ru
// Очередной вариант: теперь может вырезать контент из тэгов с параметрами, типа <p class=...>...</p>, <td ...>...</td>.

function xmf($string, $tag) {
while(true):
//начало тэга
$start = strpos($string, "<".$tag, $stop);
if ($start === false)
break;
//начало контента
$start = strpos($string, ">", $start);
if ($start === false)
break;
$start++;
//конец контента
$stop = strpos($string, "</".$tag.">", $start);
if ($stop === false)
break;
//выкусить контент!
$result[] = substr($string, $start, $stop - $start);
endwhile;
return $result;
}


// Далее можно ещё тем же методом выковырять все тэги автоматически, а
// потом весь контент распихать в массив поименованый тэгами. У меня на машине
// такой скриптех выполняется .00011 с
// А функцию я назвал XMF - "XML Fake" (ИксЭмЭль импровизированный) :)

$string = '
<news>один</news>
<news>два</news>
<news>три</news>
<news>четыре</news>
<menu>a</menu>
<menu>b</menu>
<menu>c</menu>
<menu>d</menu>
<title>aaaa</title>';


$tags = tags($string);
foreach ($tags as $val)
$xmf[$val] = xmf($string, $val);

function tags($string) {
while(true):
$start = strpos($string, '<', $stop);
if ($start === false)
break;
$start = $start + strlen($tag) + 1;
$stop = strpos($string, '>', $start);
if ($stop === false)
break;
$res = substr($string, $start, $stop - $start);
if (strpos($res, '/') === false && !in_array($res,(array)$result)):
$result[] = $res;
endif;
endwhile;
return $result;
}

function xmf($string, $tag) {
while(true):
$start = strpos($string, "<".$tag.">", $stop);
if ($start === false)
break;
$start = $start + strlen($tag) + 2;
$stop = strpos($string, "</".$tag.">", $start);
if ($stop === false)
break;
$result[] = substr($string, $start, $stop - $start);
endwhile;
return $result;
}

print_r($xmf);
?>




Играйте и выигрывайте! Интернет лотерея iLoto.net
Реклама в журнале

Copyright © <LMTH>. Все материалы являются собственностью их авторов.
При перепечатывании ссылка на http://www.magaz.org/ как на источник
информации обязательна. Правила использования материалов журнала