Warning: Cannot use a scalar value as an array in /home/admin/public_html/forum/include/fm.class.php on line 757

Warning: Invalid argument supplied for foreach() in /home/admin/public_html/forum/include/fm.class.php on line 770
Форумы портала PHP.SU :: Версия для печати :: Не пойму в чём проблема
Форумы портала PHP.SU » PHP » Регулярные выражения » Не пойму в чём проблема

Страниц (1): [1]
 

1. Rigiy - 10 Июня, 2010 - 19:09:42 - перейти к сообщению
Задача стоит в том чтоб прочитать html код и вывисти список тегов. Так же нужно прочитать некоторые параметры тегов.

Решил сделать рекурсивный обход, читая регулярными выраженями. С маленькими текстами где несколько тегов всё работает. А где большие ничего не находит. В чём может быть проблема?

Вот собсно код

PHP:
скопировать код в буфер обмена
  1. <?PHP
  2.  
  3. class Teg{
  4.         var $name;
  5.         var $size;
  6.         var $bgcolor;
  7.         var $txtcolor;
  8.         var $align;
  9.         var $valign;
  10.         var $font;
  11.         var $U;
  12.         var $I;
  13.         var $B;
  14.         var $S;
  15.  
  16.         function copy($teg){
  17.                 $this->name=$teg->name;
  18.                 $this->size=$teg->size;
  19.                 $this->bgcolor=$teg->bgcolor;
  20.                 $this->txtcolor=$teg->txtcolor;
  21.                 $this->align=$teg->align;
  22.                 $this->valign=$teg->valign;
  23.                 $this->font=$teg->font;
  24.                 $this->U=$teg->U;
  25.                 $this->I=$teg->I;
  26.                 $this->B=$teg->B;
  27.                 $this->S=$teg->S;
  28.         }
  29. }
  30.  
  31. $prev_teg=Array();                      //массив тегов родителей
  32. $count_prev_teg=1;                      //количество тегов родителей
  33. function def_teg(){
  34.         $_teg=new Teg;
  35.         $_teg->size=3;
  36.         $_teg->bgcolor="#FFFFFF";
  37.         $_teg->txtcolor="#000000";
  38.         $_teg->align="def";
  39.         $_teg->valign="def";
  40.         $_teg->font="def";
  41.         $_teg->S=0;
  42.         $_teg->B=0;
  43.         $_teg->I=0;
  44.         $_teg->U=0;
  45.         return $_teg;
  46. }
  47.  
  48. $prev_teg[0]=def_teg();
  49.  
  50. $tegs=Array();                          //Массив тегов
  51. $count_txt=0;                           //количество тегов
  52.  
  53.  
  54. function read_attr($si){
  55.         global $count_prev_teg;
  56.         global $prev_teg;
  57.         if(@$si[2]!=""){
  58.                 $prev_teg[$count_prev_teg]->size=$si[2];
  59.         }
  60.         if(@$si[4]!=""){
  61.                 $prev_teg[$count_prev_teg]->align=$si[4];
  62.         }
  63.         if(@$si[6]!=""){
  64.                 $prev_teg[$count_prev_teg]->bgcolor=$si[6];
  65.         }
  66.         if(@$si[8]!=""){
  67.                 $prev_teg[$count_prev_teg]->txtcolor=$si[8];
  68.         }
  69.         if(@$si[10]!=""){
  70.                 $prev_teg[$count_prev_teg]->valign=$si[10];
  71.         }
  72.         if(@$si[12]!=""){
  73.                 $prev_teg[$count_prev_teg]->txtcolor=$si[12];
  74.         }
  75. }
  76.  
  77. function Add_teg($si){
  78.         global $tegs;
  79.         global $count_txt;
  80.         global $count_prev_teg;
  81.         global $prev_teg;
  82.         $prev_teg[$count_prev_teg]=new Teg;
  83.         $prev_teg[$count_prev_teg]->copy($prev_teg[$count_prev_teg-1]);
  84.  
  85. preg_replace_callback("/(\s*size=\"|'?([0-9]*)\"|'?\s*)|(\s*align=\"|'?([a-z]*)\"|'?\s*)|(\s*bgcolor=\"|'?([#1-9a-fA-F]*)\"|'?\s*)|(\s*text=\"|'?([#1-9a-fA-F]*)\"|'?\s*)|(\s*valign=\"|'?([a-zA-Z]*)\"|'?\s*)|(\s*color=\"|'?([#a-zA-Z]*)\"|'?\s*)/si","read_attr",$si[2]);
  86.         switch($si[1]){
  87.                 case "u":
  88.                         $prev_teg[$count_prev_teg]->U=1;
  89.                         break;
  90.                 case "s":
  91.                         $prev_teg[$count_prev_teg]->S=1;
  92.                         break;
  93.                 case "i":
  94.                         $prev_teg[$count_prev_teg]->I=1;
  95.                         break;
  96.                 case "b":
  97.                         $prev_teg[$count_prev_teg]->B=1;
  98.                         break;
  99.                 case "strong":
  100.                         $prev_teg[$count_prev_teg]->B=1;
  101.                         break;
  102.                 case "center":
  103.                         $prev_teg[$count_prev_teg]->align="center";
  104.                         break;
  105.         }
  106.         $tegs[$count_txt]=new Teg;
  107.         $tegs[$count_txt]->copy($prev_teg[$count_prev_teg]);
  108.         $tegs[$count_txt]->name=$si[1];
  109.         $count_prev_teg++;
  110.         $count_txt++;
  111.         read($si[3]);
  112. }
  113.  
  114. function read($html){
  115.         preg_replace_callback("/<\s*([a-zA-Z]*?)(\s*.*?)>(.*?)<\s*\/\s*\\1\s*>/si","Add_teg",$html);
  116.         global $count_prev_teg;
  117.         $count_prev_teg--;
  118. }
  119.  
  120. read($html);
  121.  
  122. for($i=0;$i<$count_txt;$i++){
  123.         echo $tegs[$i]->name."<br>";
  124.  
  125. }
  126.  
  127. ?>
  128.  
2. JustUserR - 11 Июня, 2010 - 16:19:59 - перейти к сообщению
Rigiy пишет:
Решил сделать рекурсивный обход, читая регулярными выраженями. С маленькими текстами где несколько тегов всё работает. А где большие ничего не находит. В чём может быть проблема?
Скорее всего проблема в вашем случае заключается в использовании жадных квантификаторов в регулярных выражениях - в случае наличия множества тегов которые сопадаются в данным регулярным выражением они будут взять не по очереди а от самого первого открывающего и до самого последнего закрывающего тега Поэтому попробуйте добавить ко всем квантификаторам модификатор нежадности ? - то есть заменить * + ? на *? +? ?? соответственно
3. Rigiy - 14 Июня, 2010 - 17:47:07 - перейти к сообщению
JustUserR пишет:
Скорее всего проблема в вашем случае заключается в использовании жадных квантификаторов в регулярных выражениях - в случае наличия множества тегов которые сопадаются в данным регулярным выражением они будут взять не по очереди а от самого первого открывающего и до самого последнего закрывающего тега Поэтому попробуйте добавить ко всем квантификаторам модификатор нежадности ? - то есть заменить * + ? на *? +? ?? соответственно


Хм. поменял все * на *?
результат не изменился (((

вот например если так

PHP:
скопировать код в буфер обмена
  1. <?PHP
  2.  
  3. class Teg{
  4.         var $name;
  5.         var $size;
  6.         var $bgcolor;
  7.         var $txtcolor;
  8.         var $align;
  9.         var $valign;
  10.         var $font;
  11.         var $U;
  12.         var $I;
  13.         var $B;
  14.         var $S;
  15.  
  16.         function copy($teg){
  17.                 $this->name=$teg->name;
  18.                 $this->size=$teg->size;
  19.                 $this->bgcolor=$teg->bgcolor;
  20.                 $this->txtcolor=$teg->txtcolor;
  21.                 $this->align=$teg->align;
  22.                 $this->valign=$teg->valign;
  23.                 $this->font=$teg->font;
  24.                 $this->U=$teg->U;
  25.                 $this->I=$teg->I;
  26.                 $this->B=$teg->B;
  27.                 $this->S=$teg->S;
  28.         }
  29. }
  30.  
  31. $prev_teg=Array();                              //массив тегов родителей
  32. $count_prev_teg=1;                      //количество тегов родителей
  33. function def_teg(){
  34.         $_teg=new Teg;
  35.         $_teg->size=3;
  36.         $_teg->bgcolor="#FFFFFF";
  37.         $_teg->txtcolor="#000000";
  38.         $_teg->align="def";
  39.         $_teg->valign="def";
  40.         $_teg->font="def";
  41.         $_teg->S=0;
  42.         $_teg->B=0;
  43.         $_teg->I=0;
  44.         $_teg->U=0;
  45.         return $_teg;
  46. }
  47.  
  48. $prev_teg[0]=def_teg();
  49.  
  50. $tegs=Array();                          //Массив тегов
  51. $count_txt=0;                           //количество тегов
  52.  
  53.  
  54. function read_attr($si){
  55.         global $count_prev_teg;
  56.         global $prev_teg;
  57.         if(@$si[2]!=""){
  58.                 $prev_teg[$count_prev_teg]->size=$si[2];
  59.         }
  60.         if(@$si[4]!=""){
  61.                 $prev_teg[$count_prev_teg]->align=$si[4];
  62.         }
  63.         if(@$si[6]!=""){
  64.                 $prev_teg[$count_prev_teg]->bgcolor=$si[6];
  65.         }
  66.         if(@$si[8]!=""){
  67.                 $prev_teg[$count_prev_teg]->txtcolor=$si[8];
  68.         }
  69.         if(@$si[10]!=""){
  70.                 $prev_teg[$count_prev_teg]->valign=$si[10];
  71.         }
  72.         if(@$si[12]!=""){
  73.                 $prev_teg[$count_prev_teg]->txtcolor=$si[12];
  74.         }
  75. }
  76.  
  77. function Add_teg($si){
  78.         global $tegs;
  79.         global $count_txt;
  80.         global $count_prev_teg;
  81.         global $prev_teg;
  82.         $prev_teg[$count_prev_teg]=new Teg;
  83.         $prev_teg[$count_prev_teg]->copy($prev_teg[$count_prev_teg-1]);
  84.  
  85. preg_replace_callback("/(\s*?size=\"|'?([0-9]*?)\"|'?\s*?)|(\s*?align=\"|'?([a-z]*?)\"|'?\s*?)|(\s*?bgcolor=\"|'?([#1-9a-fA-F]*?)\"|'?\s*?)|(\s*?text=\"|'?([#1-9a-fA-F]*?)\"|'?\s*?)|(\s*?valign=\"|'?([a-zA-Z]*?)\"|'?\s*?)|(\s*?color=\"|'?([#a-zA-Z]*?)\"|'?\s*?)/si","read_attr",$si[2]);
  86.         switch($si[1]){
  87.                 case "u":
  88.                         $prev_teg[$count_prev_teg]->U=1;
  89.                         break;
  90.                 case "s":
  91.                         $prev_teg[$count_prev_teg]->S=1;
  92.                         break;
  93.                 case "i":
  94.                         $prev_teg[$count_prev_teg]->I=1;
  95.                         break;
  96.                 case "b":
  97.                         $prev_teg[$count_prev_teg]->B=1;
  98.                         break;
  99.                 case "strong":
  100.                         $prev_teg[$count_prev_teg]->B=1;
  101.                         break;
  102.                 case "center":
  103.                         $prev_teg[$count_prev_teg]->align="center";
  104.                         break;
  105.         }
  106.         $tegs[$count_txt]=new Teg;
  107.         $tegs[$count_txt]->copy($prev_teg[$count_prev_teg]);
  108.         $tegs[$count_txt]->name=$si[1];
  109.         $count_prev_teg++;
  110.         $count_txt++;
  111.         read($si[3]);
  112. }
  113.  
  114. function read($html){
  115.         preg_replace_callback("/<\s*?([a-zA-Z]*?)(\s*?.*?)>(.*?)<\s*?\/\s*?\\1\s*?>/si","Add_teg",$html);
  116.         global $count_prev_teg;
  117.         $count_prev_teg--;
  118. }
  119.  
  120. read("<sdgs>вам </sdgs><sdgs>вам </sdgs><sdgs>вам </sdgs><sdgs>вам </sdgs><sdgs>вам </sdgs><sdgs>вам </sdgs><sdgs>вам </sdgs><sdgs>вам </sdgs><sdgs>вам </sdgs><sdgs>вам </sdgs><sdgs>вам </sdgs><sdgs>вам </sdgs><sdgs>вам </sdgs><sdgs>вам </sdgs><sdgs>вам </sdgs><sdgs>вам </sdgs><sdgs>вам </sdgs><sdgs>вам </sdgs><sdgs>вам </sdgs><sdgs>вам </sdgs><sdgs>вам </sdgs><sdgs>вам </sdgs><sdgs>вам </sdgs><sdgs>вам </sdgs><sdgs>вам </sdgs><sdgs>вам </sdgs><sdgs>вам </sdgs><sdgs>вам </sdgs><sdgs>вам </sdgs><sdgs>вам </sdgs><sdgs>вам </sdgs><sdgs>вам </sdgs><sdgs>вам </sdgs><sdgs>вам </sdgs>");
  121. for($i=0;$i<$count_txt;$i++){
  122.         echo $tegs[$i]->name."<br>";
  123.  
  124. }
  125. ?>
  126.  


То работает. но стоит увеличить немного строку которую отправляю в функцию read(), так сразу перестаёт выводить обсалютно всё.
4. Joo - 14 Июня, 2010 - 19:24:42 - перейти к сообщению
Обходить лучше так:
PHP:
скопировать код в буфер обмена
  1. <?PHP
  2. $test=<<<HTML
  3. <html xmlns="http://www.w3.org/1999/xhtml">
  4. <head>
  5.   <title>Наши проекты</title>
  6.   <meta http-equiv="content-type" content="text/html; charset=utf-8" />
  7.   <link rel="shortcut icon" href="favicon.ico"  type="image/x-icon" />
  8.   <link rel="stylesheet" href="/templates/display.css" type="text/css" />
  9. </head>
  10. <body>
  11.     <div id="wraper">
  12.         <div id="content">
  13.             <img class="xtestlogo" src="images/xtestlogo.png" alt="" title="xTest - Наши проекты!">
  14.             <h2 class="h2"> - Проект находится в разработке &#12484;</h2>
  15.             <ul id="topMenu">
  16.               <li class="current"><a href="/?mod=portfolio" title="Портфолио">Портфолио</a></li><li><a href="/?mod=magazine" title="Магазин">Магазин</a></li><li><a href="/?mod=feedback" title="Обратная связь">Обратная связь</a></li><li><a href="/?mod=about" title="О нас">О нас</a></li>
  17.             </ul>
  18.             Вывод портфолио
  19.         </div>
  20.  
  21.     </div>
  22.     <div id="footer">
  23.         <div id="copy">&copy; 2010 <a href="http://site.ru" target="_blank">site</a> и <a href="http://xtest.org">Наши проекты</a></div>
  24.     </div>
  25. </body>
  26. </html>
  27. HTML;
  28.  
  29. function repl($m){
  30.     return ('Тег: '.$m[1].'; Атрибуты: '.$m[2].'; Текст: '.(isset($m[3])?$m[3]:'')."\n");
  31. }
  32. //Парные теги
  33. while(preg_match('%<([a-z]+\d?)(?:\s+([^<>]*?))?>((?:[^<>]|<(?!\1)[^<>]*?>)*?)</\1>%i', $test)){
  34.     $test =  preg_replace_callback('%<([a-z]+\d?)(?:\s+([^<>]*?))?>((?:[^<>]|<(?!\1)[^<>]*?>)*?)</\1>%i', "repl", $test);
  35. }
  36. //Без закрывающего тега
  37. $test =  preg_replace_callback('%<([a-z]+)(?:\s+([^<>]*?))?\s*/?>%i', "repl", $test);
  38.  
  39. echo(preg_replace('/$\s*/im', "<br />\n", $test));
  40. ?>

Вот тут можно реультат скрипта посмотреть: http://xtest[dot]org/test.php
5. Rigiy - 14 Июня, 2010 - 21:46:35 - перейти к сообщению
Joo списиб. Эт гораздо лучше моего кода, рег выражения у мну кривые...
постараюсь это переделать под себя маленька. Просто нужно чтоб была возможность отслеживания наследования атрибутов дочернего тега, от тега родителя. Потому и делал рекурсивно...
6. JustUserR - 15 Июня, 2010 - 01:33:23 - перейти к сообщению
Rigiy пишет:
Просто нужно чтоб была возможность отслеживания наследования атрибутов дочернего тега, от тега родителя. Потому и делал рекурсивно...
Рекурсивный способ достаточно удобен во многих случаях но при работе с регулярными выражениями надо учитывать следующее - например если вы находите определенный текстовый элемент и хотите продолжать поиск в нем то его нужно скопировать как выделенную подстроку и работать с ним отдельно в шаге рекурсии
Также можно использовать операторы просмотра вперед и назад
7. Joo - 16 Июня, 2010 - 05:25:17 - перейти к сообщению
Rigiy пишет:
Просто нужно чтоб была возможность отслеживания наследования атрибутов дочернего тега


Тогда необходимо двигаться строго от внешнего тега к внутреннему, в моем примере берется тег максимально верхнего уровня, в котором нет тегов ему подобных.

Как сделать с помощью регулярных выражений выборку тегов строго в порядке вложенности я пока еще не придумал, или знаний не хватает или просто регулярные выражения не предназначены для этого и нужно писать свой парсер или искать готовые решения.

Подобный код, как описан выше, я использовал для обработки шаблонов типа
CODE (html):
скопировать код в буфер обмена
  1. {each...}...{end each} {if...}...{end if}
, своего шаблонизатора, в данном случае он справлялся со своей задачей на 100%.
8. JustUserR - 16 Июня, 2010 - 13:03:40 - перейти к сообщению
Joo пишет:
Как сделать с помощью регулярных выражений выборку тегов строго в порядке вложенности
Дейстивтельно если имя вложенных тегов является одинаковым то даже если они имеют различные аттрибуты и идентификаторы - то вследствие одинаковости закрывающего тега их поиск по вложенности с помощью *? так просто не функционирует - тем более что теги могут оказаться не неверно-закрытыми не в том порядке или не закрыты вообще
Однако существует общий последовательный механизм такого разбора за счет проверки парности тегов и их сохранение в стек - таким образом можно временно переименовать все одноименные теги по их уровню вложенност с приданием им определенных индексов - которые в свою очередь заключены в специальные символы не разрешенные по умолчанию в теге и используемые для последующего обратного расширования - например [tag][tag][/tag][/tag] переименуется в [tag<0>][tag<1>][/tag<1>][/tag<0>] После такой посдтановки можно применять обычной регулярное выражение с рекурсивным разбором
9. Joo - 16 Июня, 2010 - 14:13:56 - перейти к сообщению
JustUserR пишет:
например [tag][tag][/tag][/tag] переименуется в [tag<0>][tag<1>][/tag<1>][/tag<0>]


Я думал об этом, и наверное это единственный способ обработки с помощью регулярок, но скорость упадет в два раза.
10. JustUserR - 17 Июня, 2010 - 10:58:41 - перейти к сообщению
Joo пишет:
Я думал об этом, и наверное это единственный способ обработки с помощью регулярок, но скорость упадет в два раза.
В принципе это не так уж и медленный способ - если вы хотите проверять правильности вложенности тегов и их закрытость то в любом случае придется делать рекурсивный обход - и в таком случае пометка тегов индексами и последующая их очистка не займет так много времени
11. Joo - 17 Июня, 2010 - 12:08:15 - перейти к сообщению
JustUserR пишет:
В принципе это не так уж и медленный способ - если вы хотите проверять правильности вложенности тегов и их закрытость то в любом случае придется делать рекурсивный обход - и в таком случае пометка тегов индексами и последующая их очистка не займет так много времени


Да если следует перебрать строго в порядке вложенности, то да, согласен это хороший способ, как раз для задачи автора темы.
12. Rigiy - 17 Июня, 2010 - 18:20:36 - перейти к сообщению
Вот сделал немного кривых набросков )))
Вроде как работает ) Но не учитывает того что код может быть написан криво, тоесть , будут встречатся не закрывающиеся теги. Но я думаю это тут уже можно будет легко поправить. Всем спасибо за помощь =)




PHP:
скопировать код в буфер обмена
  1. <?PHP
  2. class Teg{
  3.         var $name;
  4.         var $size;
  5.         var $bgcolor;
  6.         var $txtcolor;
  7.         var $align;
  8.         var $valign;
  9.         var $font;
  10.         var $U;
  11.         var $I;
  12.         var $B;
  13.         var $S;
  14.  
  15.         function copy($teg){
  16.                 $this->name=$teg->name;
  17.                 $this->size=$teg->size;
  18.                 $this->bgcolor=$teg->bgcolor;
  19.                 $this->txtcolor=$teg->txtcolor;
  20.                 $this->align=$teg->align;
  21.                 $this->valign=$teg->valign;
  22.                 $this->font=$teg->font;
  23.                 $this->U=$teg->U;
  24.                 $this->I=$teg->I;
  25.                 $this->B=$teg->B;
  26.                 $this->S=$teg->S;
  27.         }
  28. }
  29.  
  30.  
  31. class Stack{
  32.         var $st;
  33.         var $count;
  34.  
  35.         function Stack(){
  36.                 $this->st=array();
  37.                 $this->count=0;
  38.         }
  39.  
  40.         function add($teg){
  41.                 $this->st[$this->count]=new Teg;
  42.                 $this->st[$this->count]->copy($teg);
  43.                 if($this->st[$this->count]->size==""){
  44.                         $this->st[$this->count]->size=$this->st[$this->count-1]->size;
  45.                 }
  46.                 if($this->st[$this->count]->bgcolor==""){
  47.                         $this->st[$this->count]->bgcolor=$this->st[$this->count-1]->bgcolor;
  48.                 }
  49.                 if($this->st[$this->count]->txtcolor==""){
  50.                         $this->st[$this->count]->txtcolor=$this->st[$this->count-1]->txtcolor;
  51.                 }
  52.                 if($this->st[$this->count]->align==""){
  53.                         $this->st[$this->count]->align=$this->st[$this->count-1]->align;
  54.                 }
  55.                 if($this->st[$this->count]->valign==""){
  56.                         $this->st[$this->count]->valign=$this->st[$this->count-1]->valign;
  57.                 }
  58.                 if($this->st[$this->count]->U==""){
  59.                         $this->st[$this->count]->U=$this->st[$this->count-1]->U;
  60.                 }
  61.                 if($this->st[$this->count]->I==""){
  62.                         $this->st[$this->count]->I=$this->st[$this->count-1]->I;
  63.                 }
  64.                 if($this->st[$this->count]->B==""){
  65.                         $this->st[$this->count]->B=$this->st[$this->count-1]->B;
  66.                 }
  67.                 if($this->st[$this->count]->S==""){
  68.                         $this->st[$this->count]->S=$this->st[$this->count-1]->S;
  69.                 }
  70.                 $this->count++;
  71.         }
  72.  
  73.         function del(){
  74.                 $this->count--;
  75.                 unset($this->st[$this->count]);
  76.         }
  77.  
  78.         function tdata(){
  79.                 return $this->st[$this->count-1];
  80.         }
  81.  
  82.         function tname(){
  83.                 return $this->st[$this->count-1]->name;
  84.         }
  85. }
  86.  
  87. class TList{
  88.         var $teg;
  89.         var $count;
  90.  
  91.         function TList(){
  92.                 $this->teg=array();
  93.                 $this->count=0;
  94.         }
  95.  
  96.         function add($teg){
  97.                 $this->teg[$this->count]=new Teg;
  98.                 $this->teg[$this->count]->copy($teg);
  99.                 $this->count++;
  100.         }
  101.  
  102.         function tdata($i){
  103.                 if($i>=$this->count){
  104.                         return "error";
  105.                 }
  106.                 return $this->teg[$i];
  107.         }
  108.  
  109.         function tname($i){
  110.                 if($i>=$this->count){
  111.                         return "error";
  112.                 }
  113.                 return $this->teg[$i]->name;
  114.         }
  115.  
  116.         function out(){
  117.                 for($i=0;$i<$this->count;$i++){
  118.                         echo $this->tname($i)."<br>";
  119.                 }
  120.         }
  121. }
  122.  
  123.  
  124.  
  125.  
  126. function def_teg(){
  127.         $_teg=new Teg;
  128.         $_teg->size=3;
  129.         $_teg->bgcolor="#FFFFFF";
  130.         $_teg->txtcolor="#000000";
  131.         $_teg->align="def";
  132.         $_teg->valign="def";
  133.         $_teg->font="def";
  134.         $_teg->S="0";
  135.         $_teg->B="0";
  136.         $_teg->I="0";
  137.         $_teg->U="0";
  138.         return $_teg;
  139. }
  140.  
  141. function null_teg(){
  142.         $_teg=new Teg;
  143.         $_teg->size="";
  144.         $_teg->bgcolor="";
  145.         $_teg->txtcolor="";
  146.         $_teg->align="";
  147.         $_teg->valign="";
  148.         $_teg->font="";
  149.         $_teg->S="";
  150.         $_teg->B="";
  151.         $_teg->I="";
  152.         $_teg->U="";
  153.         return $_teg;
  154. }
  155.  
  156.  
  157.  
  158. $prev_teg=new Stack;
  159. $temp_teg=new Teg;
  160. $temp_teg->copy(null_teg());
  161.  
  162.  
  163. $prev_teg->add(def_teg());
  164.  
  165. $tegs=new TList;
  166.  
  167.  
  168. function read_attr($si){
  169.         global $temp_teg;
  170.         if(@$si[2]!=""){
  171.                 $temp_teg->size=$si[2];
  172.         }
  173.         if(@$si[4]!=""){
  174.                 $temp_teg->align=$si[4];
  175.         }
  176.         if(@$si[6]!=""){
  177.                 $temp_teg->bgcolor=$si[6];
  178.         }
  179.         if(@$si[8]!=""){
  180.                 $temp_teg->txtcolor=$si[8];
  181.         }
  182.         if(@$si[10]!=""){
  183.                 $temp_teg->valign=$si[10];
  184.         }
  185.         if(@$si[12]!=""){
  186.                 $temp_teg->txtcolor=$si[12];
  187.         }
  188. }
  189.  
  190. function Add_teg($si){
  191.         if(stristr($si[1],"area")){
  192.                 return;
  193.         }
  194.         if(stristr($si[1],"base")){
  195.                 return;
  196.         }
  197.         if(stristr($si[1],"br")){
  198.                 return;
  199.         }
  200.         if(stristr($si[1],"col")){
  201.                 return;
  202.         }
  203.         if(stristr($si[1],"hr")){
  204.                 return;
  205.         }
  206.         if(stristr($si[1],"img")){
  207.                 return;
  208.         }
  209.         if(stristr($si[1],"input")){
  210.                 return;
  211.         }
  212.         if(stristr($si[1],"link")){
  213.                 return;
  214.         }
  215.         if(stristr($si[1],"meta")){
  216.                 return;
  217.         }
  218.         if(stristr($si[1],"param")){
  219.                 return;
  220.         }
  221.         global $tegs;
  222.         global $temp_teg;
  223.         global $prev_teg;
  224.         if(stristr($si[1],"/")){
  225.                 $prev_teg->del();
  226.                 return;
  227.         }
  228.  
  229. preg_replace_callback("/(\s*?size=\"|'?([0-9]*?)\"|'?\s*?)|(\s*?align=\"|'?([a-z]*?)\"|'?\s*?)|(\s*?bgcolor=\"|'?([#1-9a-fA-F]*?)\"|'?\s*?)|(\s*?text=\"|'?([#1-9a-fA-F]*?)\"|'?\s*?)|(\s*?valign=\"|'?([a-zA-Z]*?)\"|'?\s*?)|(\s*?color=\"|'?([#a-zA-Z]*?)\"|'?\s*?)/si","read_attr",@$si[2]);
  230.         switch($si[1]){
  231.                 case "u":
  232.                         $temp_teg->U=1;
  233.                         break;
  234.                 case "s":
  235.                         $temp_teg->S=1;
  236.                         break;
  237.                 case "i":
  238.                         $temp_teg->I=1;
  239.                         break;
  240.                 case "b":
  241.                         $temp_teg->B=1;
  242.                         break;
  243.                 case "strong":
  244.                         $temp_teg->B=1;
  245.                         break;
  246.                 case "center":
  247.                         $temp_teg->align="center";
  248.                         break;
  249.         }
  250.         $temp_teg->name=$si[1];
  251.         $prev_teg->add($temp_teg);
  252.         $tegs->add($prev_teg->tdata());
  253.         $temp_teg->copy(null_teg());
  254.  
  255. }
  256.  
  257.  
  258. function read($html){
  259.  
  260.         preg_replace_callback("/<\s*?([\/a-z]+\d?)(?:\s+([^<>]*?))?\s*?>/si","Add_teg",$html);
  261.  
  262. }
  263.  
  264. read($htm);
  265.  
  266. $tegs->out();
  267.  
  268. ?>
13. JustUserR - 18 Июня, 2010 - 12:56:16 - перейти к сообщению
Joo пишет:
Да если следует перебрать строго в порядке вложенности, то да, согласен это хороший способ, как раз для задачи автора темы.
Да вы правы - а можно попытаться решать данную задачу еще одним путем с организацией собственной упрощенной аналогии DOM-модели - то есть после рекурсивного считывания тегов они сохраняются в специльное дерево - где проставляются их связи и зависимости и указывается наследование аттрибутов и тд - а в конце они обратно собираются в общую строку

 

Powered by ExBB FM 1.0 RC1