WordPress и класс HtmlParser Печать
Автор: А.Волос   

Каждая программа имеет свою пред-историю. Это то, что побудило написать ее.

Я знаком с несколькими CMS. Среди них Joomla, HostCMS и некоторые другие. Возникла необходимость познакомиться с CMS WordPress. Нет такого программиста, который бы не захотел заглянуть в исходный код каждой новой CMS. Например исходный код  Joomla состоит примерно из 3000 файлов! Таков ее вес.  CMS  WordPress намного, намного легче. В этом ее несомненное достоинство перед Joomla.

Посмотрим например файлы шаблона WordPress. Для примера те файлы, которые находятся в каталоге:

wordpress\wp-content\themes\twentythirteen>

Это так называемые темы. Это тема twentythirteen, которая включена в дистрибутив по умолчанию.  Что мы там видим? В корне каталога мы видим порядка 30 php-файлов, которые расписывают тему. Имена этих файлов в разных темах в большинстве случаев совпадают. Раскрывая эти файлы по F4 или F3 мы видим "слепой" php-код с фрагментами html-кода. Неудобно.

Хорошо бы если бы код этих php-файлов был расцвечен, например html-код синим, комментарии - зеленым, отдельные php-команды другими цветами. Насколько легче рассматривать php расцвеченный код! Что касается меня, то я почти никогда не изучаю код в его слепом виде. Конечно, Notepad++ сделает все как надо, но не всегда хочется рассматривать файлы в Notepad.

Кроме этого гораздо удобнее было бы если бы каждый php-файл шаблона находился на отдельной странице, между страницами была бы навигация, отдельные страницы были бы собраны в главу, а у главы было бы оглавление страниц. Из глав можно было бы создать книгу. Я всегда, когда пишу программу или изучаю программу все свои действия, код функций, тесты, многочисленные варианты и тд. пишу в такую отдельную книгу. Естественно с рацвеченным кодом. Новая программа - новая книга. Такая тактика себя полностью оправдывает и окупается сторицей. Иначе можно безнадежно утонуть в ворохе файлов, функций, вариантов, миллионов строк кода. Через три месяца можешь не узнать собственный код, думая, а действительно ли это я написал?

Ну что-ж, было бы желание. PHP-язык имеет все возможности, чтобы претворить эти желания в жизнь. Тогда, нажав одну кнопку один раз мы будем иметь и книгу, и главы, и страницы с расцвеченным кодом всех php-файлов шаблона. Программа все это сделает за нас!

А начнем мы с расцветки кода:

 

В этом нам поможет класс HtmlParser.

Вообще в программировании уже все задачи давно кем-нибудь решены. Как в поговорке: "О любви не говори. О ней все сказано.". Значит ли это что больше не надо писать новых программ? А вдруг они будут хуже тех, которые уже есть?

Класс  HtmlParser написал человек по имени Jose Solorzano в 2003 году. Файл с этим классом был "пойман" мной в интернете. Посмотрел. А что? Вполне подходящий класс, чтобы парсить не только html, но и php-код.  Надо его только чуть-чуть переделать под наши нужды. О, это мое любимое занятие, чуть-чуть переделывать чей-то код! Это как пить чай с малиновым вареньем.

Суть класса  HtmlParser в том, чтобы разбить парсимый код на лексемы нескольких типов, к примеру: тип Комментарий, тип HTML-тег, тип PHP-тег, тип Текст. Каждую из этих лексем сохранить в структуре состоящей из трех полей - Тип, Имя, Значение. Сама лексема будет сохранена в поле Значение, а ее тип в поле Тип. Имя можно дать в соответствии с ее типом. Все эти структуры можно сохранять в простой массив,  по ходу парсинга. Таким образом в массиве структур будет сохранен весь текст парсимого файла.

Далее просто выводя из массива в новый файл данные структура за структурой будем окрашивать значение каждой структуры (а это фрагмент текста) в свой цвет в зависимости от типа структуры.

Код класса при внимательном рассмотрении становится совершенно понятным. Сначала парсимый файл считывается в строку при помощи вызванной в файле index.php функции HtmlParser_ForFile(), в которой считанная строка передается конструктору класса HtmlParser() при создании объекта класса. Конструктор инициирует все необходимые переменные класса, записывает в переменную iHtmlText переданную в параметре строку, устанавливает указатель iHtmlTextIndex в нулевую позицию строки. Далее, в файле index.php,  вызывается функция structOfTag(), которая в цикле вызывает метод parse() класса до тех пор, пока не будет найден конец строки.

Несколько слов о файле index.php. Этот файл и создает html-книгу и ее страницы, и записывает в эти страницы расцвеченный php-код.

Примечание:  Парсимые файлы помещаются в директорию from2. Результат - книга в html-формате находится в директории booktest.

Кстати, ни в коем случае не стремился написать программу прекрасную во всех отношениях. Довольно того, что программа выполняет поставленную перед ней задачу, и при этом избавляет программиста от рутинного труда, дарит драгоценное время! Много не тестировал ее. Проверил только на шаблонах включенных в дистрибутив WordPress. Ошибок не наблюдал.

Скачать файлы с исходным кодом можно здесь: WordPress и HtmlParser

 

index.php


<?php 

require_once(dirname(__FILE__) . '/' . 'utilities/htmlparser.php');

$target = array(
'<?php','?>',
'endwhile','while',
'endif','if',
'else','elseif',
'/*','*/');

$replace   = array(//мягкий знак - буква Ять
'<FONT COLOR="#dc2300"><?php</FONT>',
'<FONT COLOR="#dc2300">?></FONT>',
'<FONT COLOR="#00ae00"><B>endwhile</B></FONT>',
'<FONT COLOR="#00ae00"><B>while</B></FONT>',
'<FONT COLOR="#00ae00"><B>endif</B></FONT>',
'<FONT COLOR="#00ae00"><B>if</B></FONT>',
'<FONT COLOR="#00ae00"><B>else</B></FONT>',
'<FONT COLOR="#00ae00"><B>elseif</B></FONT>',
'<FONT COLOR="#5c8526">/*',
'*/</FONT>'
);



//объявим массивы 
$masNameFrom = array(); 

  //----------------------------- 
  // откроем файл для записи ошибок 
  $filename = "error.txt"; 
  if(!($myErrorFile = fopen($filename, "w"))) {
    print("Error: "); 
    print("'$filename' could not be created\n"); 
    exit; 
  } 
  //----------------------------- 
  // open directory 
  $myDirectoryFrom = opendir("from1"); 
  $n=0; 
  // считаем в массив имена файлов из from1 
  while(FALSE !== ($entryName = readdir($myDirectoryFrom))) {
      $masNameFrom[$n] = $entryName; 
  $n++; 
  } 
  // сосчитаем количество элементов в массиве (файлов в директории) 
  $indexLimit = count($masNameFrom); 
  //----------------------------- 
  // open directory (в этой директории файлы WordPress!)
  $myDirectoryFrom2 = opendir("from2"); 
  $k=0; 
  // считаем в массив имена файлов из from2 
  while(FALSE !== ($entryName2 = readdir($myDirectoryFrom2))) {
      $masNameFrom2[$k] = $entryName2; 
  $k++; 
  } 
  // сосчитаем количество элементов в массиве (файлов в директории) 
  $indexLimit2 = count($masNameFrom2); 

for($index=2;$index<$indexLimit;$index++) {

    $nameFile = $masNameFrom[$index]; //имя файла
    $nameFile2 = $masNameFrom2[$index]; //имя файла
          
    //--------------------------- 
    //откроем первый исходный файл для чтения 
    $Temp = "from1/"; 
    $filenameFrom = "$Temp$nameFile"; //имена такие (выбраны из массива имен): "from1/Gl_01_03.html" 
    if(!($mySourceFile = fopen($filenameFrom, "r"))) {
        fputs($myErrorFile, "'$filenameFrom' could not be created\n" ); 
        exit; 
    }

    //--------------------------- 
    //откроем второй исходный файл для чтения 
    $Temp2 = "from2/"; 
    $filenameFrom2 = "$Temp2$nameFile2"; //имена такие (выбраны из массива имен): "from2/page.php  и тд" 

    $parser = HtmlParser_ForFile ($filenameFrom2);
    //print_r($parser);

    //откроем файл в каталоге to1 чтобы записать в него.
    $Temp3 = "to1/"; 
    $filenameTo = "$Temp3$nameFile"; //имена такие (выбраны из массива имен): "from1/Gl_01_03.html" 
    if(!($myFileTo = fopen($filenameTo, "w"))) {
        fputs($myErrorFile, "'$filenameTo' could not be opened\n" ); 
        exit; 
    } 
    $kn=0;
    $flag = false;
    $strTemp = "";
    //считаем построчно из первого исходного файла from в файл to 
    while(!feof($mySourceFile)) {
        
        //читаем строку из файла
        $myLine = fgets($mySourceFile, 1080);
        $str_temp = trim($myLine);

        if($kn<45){//скопируем без изменений 45 строк
            fputs($myFileTo, $myLine);
            $kn++;
            continue;
        }
///////////////////////////////////////////////////
///////////////////////////////////////////////////
///////////////////////////////////////////////////
        if($flag==false){
            fputs($myFileTo, "<h2>$nameFile2 </h2>"); //вставка имени файла в заголовок страницы
            fputs($myFileTo, '<hr>'); //вставка 
            fputs($myFileTo, ''); //вставка 

            $masStruc = structOfTag($parser);
            $col_str = count($masStruc);
            //print_r($masStruc);

            $strout = "";
            $nodevalue = "";

            for($i=0;$i<$col_str;$i++){//просканируем массив структур
        
                $elem_temp = $masStruc[$i];
                $type  = $elem_temp[struct][type];
                $name  = $elem_temp[struct][name];
                $value = $elem_temp[struct][value];
				
				if($type == NODE_TYPE_TAGELEMENT 
				   || $type == NODE_TYPE_TAGBEGINELEMENT
				   || $type == NODE_TYPE_TAGENDELEMENT
				   || $type == NODE_TYPE_ENDELEMENT){

					$strtemp1 = htmlentities($value);
					$strtemp2 = str_replace($target,$replace,$strtemp1);
					$strtempOut = '<FONT COLOR="#2300dc">'.$strtemp2.'</FONT>';
				   
				}
				elseif($type == NODE_TYPE_COMMENT){
					$strtemp1 = htmlentities($value);
					$strtemp2 = str_replace($target,$replace,$strtemp1);
					$strtempOut = '<FONT COLOR="#5c8526">'.$strtemp2.'</FONT>';
				
				}
                else{
					$strtemp1 = htmlentities($value);
					$strtempOut = str_replace($target,$replace,$strtemp1);

                }				

                $strout .= $strtempOut;//сохраним в строку значение структуры
				
            }
			
            fputs($myFileTo, $strout); //запишем строку в файл

            fputs($myFileTo, ''); //вставка 
            fputs($myFileTo, '<hr>'); //вставка 
            $flag = true;
        }
///////////////////////////////////////////////////
///////////////////////////////////////////////////
///////////////////////////////////////////////////

        fputs($myFileTo, $myLine); //запишем оставшиеся строки в файл-приемник

                
    }//end while

    // закроем файлы 
    fclose($mySourceFile);       
    fclose($myFileTo); 
///////////////////////////////////////////////////////////

}//end for

  // close directory 
  closedir($myDirectoryFrom2); 
  closedir($myDirectoryFrom); 
  //-------------------------------- 
///////////////////////////////////////////////////
///////////////////////////////////////////////////
///////////////////////////////////////////////////
///////////////////////////////////////////////////
///////////////////////////////////////////////////
///////////////////////////////////////////////////
    //--------------------------- 
    //откроем третий исходный файл для чтения 
    $Temp3 = "from3/Gl_01_01.html"; 
    $filenameFrom3 = "$Temp3"; //имена такие (выбраны из массива имен): "from2/page.php  и тд" 

    if(!($mySourceFile3 = fopen($filenameFrom3, "r"))) {
        fputs($myErrorFile, "'$filenameFrom3' could not be created\n" ); 
        exit; 
    }

    //откроем файл в каталоге to1 чтобы записать в него.
    $Temp3 = "to1/Gl_01_01.html"; 
    $filenameTo = "$Temp3"; //имена такие (выбраны из массива имен): "from1/Gl_01_03.html" 
    if(!($myFileTo = fopen($filenameTo, "w"))) {
        fputs($myErrorFile, "'$filenameTo' could not be opened\n" ); 
        exit; 
    } 

    $ind = 2;   
    //считаем построчно из третьего исходного файла from в файл to 
    while(!feof($mySourceFile3)) {
        
        //читаем строку из файла
        $myLine = fgets($mySourceFile3, 1080);
        $myLine = " ".$myLine;

        $pp = strpos($myLine,'<li><a href');
        if($pp){//
                
            if(strpos($myLine,'Gl_01_02.html')){
                fputs($myFileTo, $myLine);
                continue;
            }
                        
            if($ind<$indexLimit2){
                // имя файла 
                $fileNN = $masNameFrom2[$ind]; 

                $myNewLine = str_replace('</a>
',"$fileNN</a>
",$myLine); 
                fputs($myFileTo, $myNewLine);
                $ind++;
                continue;
            }
        }

        fputs($myFileTo, $myLine);

    }   

    fclose($mySourceFile3);      
    fclose($myFileTo); 
    fclose($myErrorFile); 
	
require_once(dirname(__FILE__) . '/' . 'index2.php');
        
  
  ?> 

 

index2.php

<?php 

  //объявим массивы 
  $masNameFrom = array(); 
  $masNameTo = array(); 

  $target = ""; 
  $replacement = "";

  //----------------------------- 
  // откроем файл для записи ошибок 
  $filename = "error.txt"; 
  if(!($myFile = fopen($filename, "w"))) {
    print("Error: "); 
    print("'$filename' could not be created\n"); 
    exit; 
  } 
  //----------------------------- 
  // open directory 
  $myDirectoryFrom = opendir("to1"); 
  $n=0; 
  // считаем в массив имена файлов из from1 
  while(FALSE !== ($entryName = readdir($myDirectoryFrom))) {
  $masNameFrom[$n] = $entryName; 
  $n++; 
  } 
  // сосчитаем количество элементов в массиве 
  $indexLimit = count($masNameFrom); 
  // для каждого имени файла повторим цикл 
  for($index=2; $index < $indexLimit; $index++) {

    //--------------------------- 
    // откроем файл для чтения 
    $Temp = "to1/"; 
    $filenameFrom = "$Temp$masNameFrom[$index]"; 
    if(!($myFileFrom = fopen($filenameFrom, "r"))) {
      fputs($myFile, "'$filenameFrom' could not be opened\n" ); 
      exit; 
    } 

    //--------------------------- 
    //откроем файл для записи 
    $Temp1 = "booktest/Gl_01/"; 
    $filenameTo = "$Temp1$masNameFrom[$index]"; 
    if(!($myFileTo = fopen($filenameTo, "w"))) {
      fputs($myFile, "'$filenameTo' could not be created\n" ); 
      exit; 
    } 

    //--------------------------- 
    //считаем построчно из файла from в файл to 
    while(!feof($myFileFrom)) {

      //читаем строку из файла 
      $myLine = fgets($myFileFrom, 1024); 
      fputs($myFileTo, "$myLine");

    } 

    // закроем файлы 
    fclose($myFileFrom); 
    fclose($myFileTo); 
  }//end for 

  //-------------------------------- 
  // close directory 
  closedir($myDirectoryFrom); 
  fclose($myFile); 
  //-------------------------------- 
?> 



 

htmlparser.php


<?php

//define ("NODE_TYPE_START",0);
define ("NODE_TYPE_TAGELEMENT",1);       //полностью сформированный открывающий HTML-тег
define ("NODE_TYPE_TAGBEGINELEMENT",10); //только открывающая '<'
define ("NODE_TYPE_TAGENDELEMENT",11);   //только закрывающая '>'

define ("NODE_TYPE_PHPELEMENT",7);      //полностью сформированный открывающий PHP-тег
define ("NODE_TYPE_PHPBEGINELEMENT",8); //только открывающая 'php'
define ("NODE_TYPE_PHPENDELEMENT",9);   //только закрывающая 'php'

//define ("NODE_TYPE_ELEMENT",2);
define ("NODE_TYPE_TEXT",3);            //текст
define ("NODE_TYPE_ENDELEMENT",4);      //полностью сформированный закрывающий HTML-тег
define ("NODE_TYPE_COMMENT",5);         //комментарий
define ("NODE_TYPE_DONE",6);

class HtmlParser {

    var $iNodeType;
    var $iNodeName = "";
    var $iNodeValue = "";

    // The following fields should be 
    // considered private:

    var $iHtmlText;
    var $iHtmlTextLength;
    var $iHtmlTextIndex = 0;
    var $iHtmlCurrentChar;
    var $BOE_ARRAY;
    var $B_ARRAY;
    var $BOS_ARRAY;
    var $BO_ARRAY;      
    var $NN_ARRAY;      
    
    /**
     * Constructor.
     * Constructs an HtmlParser instance with
     * the HTML text given.
     */
    function HtmlParser ($aHtmlText) {
        $this->iHtmlText = $aHtmlText;
        $this->iHtmlTextLength = strlen($aHtmlText);
        $this->iNodeAttributes = array();
        $this->setTextIndex (0);

        $this->BOE_ARRAY = array (" ", "\t", "\r", "\n", "=" );
        $this->B_ARRAY = array (" ", "\t", "\r", "\n" );
        $this->BOS_ARRAY = array (" ", "\t", "\r", "\n", "/" );
                $this->BO_ARRAY = array ("<" );
        $this->NN_ARRAY = array (" ", "\t", "\r", "\n", "=","'" );
    }

    /**
     * Method parse.
     * Parses the next node. Returns false only if
     * the end of the HTML text has been reached.
     * Updates values of iNode* fields.
     */
 
    function parse() {
        
        $text = $this->skipToElement();

        if ($text != "") {

            $ppp = strpos($text, ">");
            $mm = substr($text, 0, 1) == ">";
            
            //найдена закрывающая угловая скобка!
            if($ppp || $mm){// 
                        
                //проверим - это закрытие html-тега или php-тега?
                $rest = substr($text, 0, ($ppp+1)); 
                $rr = substr($rest, -2); 
                                
                if($rr=="?>"){// закрытие php-тега
                    $this->iNodeType = NODE_TYPE_PHPENDELEMENT;
                    $this->iNodeName = "phpEndELEMENT";
                    $this->iNodeValue = "$rest";
                }
                elseif($rr=="=>" || $rr=="->"){
                    $this->iNodeType = NODE_TYPE_TEXT;
                    $this->iNodeName = "Text";
                    $this->iNodeValue = $text;
                    return true;                                 
                } 
                elseif($mm==">"){
                    $this->iNodeType = NODE_TYPE_TAGENDELEMENT;
                    $this->iNodeName = "TagEndELEMENT";
                    $this->iNodeValue = "$text";
                    return true;
                }
                else{
                    $this->iNodeType = NODE_TYPE_TAGENDELEMENT;
                    $this->iNodeName = "TagEndELEMENT";
                    $this->iNodeValue = "$rest";
                }

                $slen = strlen($text); 
                $this->iHtmlTextIndex = $this->iHtmlTextIndex - $slen; //вернем указатель на начало подстроки

                if($this->iCurrentChar=='<'){$this->moveNext();} //перешагнем через угловую скобку

                $this->skipEndOfTag();
                return true;  
            }
            else{// NODE_TYPE_TEXT
                $this->iNodeType = NODE_TYPE_TEXT;
                $this->iNodeName = "Text";
                $this->iNodeValue = $text;
                return true;
            }

        }//end if ($text != "")
                
        return $this->readTag();
    }
 

    function clearAttributes() {
        $this->iNodeAttributes = array();
    }


    function readTag() {
        
        if ($this->iCurrentChar != "<") {
            $this->iNodeType = NODE_TYPE_DONE;
            return false;
        }
        $this->clearAttributes();
        $this->skipMaxInTag ("<", 1);

        /*****
         * 1. Спарсим ЗАКРЫВАЮЩИЙ ТЕГ узла 
         * в  $name - закрывающий тег узла!
         */
        if ($this->iCurrentChar == '/') {
            $this->moveNext();
            $name = $this->skipToBlanksInTag();
            $name = '</'.$name.'>';
            $this->iNodeType = NODE_TYPE_ENDELEMENT;
            $this->iNodeName = "EndELEMENT";
            $this->iNodeValue = $name;            

            $this->skipEndOfTag();
            return true;
        }
///////////////////////////////////////////////////////////////
        /*****
         * 1. Если  символ, следующий за '<' - плохой? 
         * 
         */
        $chhars = $this->NN_ARRAY;               
        $chs = count($chhars);
        $chch = $this->iCurrentChar;            
        for ($idx = 0; $idx < $chs; $idx++) {
            if ($chch == $chhars[$idx]) {
                $this->moveNext();
                $name = $this->skipToElement();
                $name = '<'.$chch."$name";
                $this->iNodeType = NODE_TYPE_TEXT;
                $this->iNodeName = "Text";
                $this->iNodeValue = $name;  
                return true;
            }
        }                       
///////////////////////////////////////////////////////////////
        $name = $this->skipToBlanksOrSlashInTag(); 

        if (!$this->isValidTagIdentifier ($name)) {//валидация 

            /*****
             * 2. Спарсим КОММЕНТАРИЙ 
             * в  $name - комментарий!
             */
            $comment = false;

            if (strpos($name, "!--") === 0) {

                if (strpos($name, "--", 3) === (strlen($name) - 2)) {
                    $this->iNodeType = NODE_TYPE_COMMENT;
                    $this->iNodeName = "Comment";
                    $this->iNodeValue = "<" . $name . ">";
                    $comment = true;    
                }
                else {
                    $rest = $this->skipToStringInTag ("-->");    
                    if ($rest != "") {
                        $this->iNodeType = NODE_TYPE_COMMENT;
                        $this->iNodeName = "Comment";
                        $this->iNodeValue = "<" . $name . $rest;
                        $comment = true;
                        // Already skipped end of tag
                        return true;
                    }
                }
            }
///////////////////////////////////////////////////////////////

            /*****
             * 3. Спарсим ОТКРЫВАЮЩИЙ ТЕГ узла 
             * в $name - имя открывающего тега!
             */                              
            if (!$comment) {
                //1. 
                if(strpos($name, "?php") === 0){//это ИМЯ '?php' открывающего тега узла!

                    $name = "<" . $name; 

                    $text = $this->skipToInTag($this->BO_ARRAY);
                                        
                    if($this->iCurrentChar =='>'){
                        $text .= ">";
                        $this->moveNext();                                              
                    }
                                        
                    if ($text != "") {
                                        
                        $ppp = strpos($text, ">");
            
                        if($ppp){  

                            $name .= $text;
                                                        
                            $this->iNodeType = NODE_TYPE_PHPELEMENT;
                            $this->iNodeName = "phpELEMENT";
                            $this->iNodeValue = $name;            
                            return true;  

                        }
                        else{ 

                            $name .= $text;
                                                        
                            $this->iNodeType = NODE_TYPE_PHPBEGINELEMENT;
                            $this->iNodeName = "phpBeginELEMENT";
                            $this->iNodeValue = $name;
                            return true;
                        }

                    }

                }
                // 2.
                else{//это ИМЯ 'iCurrentChar=='>'){

                        $name = $name.">";
                        $this->iNodeType = NODE_TYPE_TAGELEMENT;
                        $this->iNodeName = "TagELEMENT";
                        $this->iNodeValue = $name;
                        $this->moveNext();
                        return true;                                        
                    }
                                        
                    $text = $this->skipToElement();

                    if ($text != "") {

                        $ppp = strpos($text, ">");

                        if($ppp){  

                            $slen = strlen($text); 
                            $this->iHtmlTextIndex = $this->iHtmlTextIndex - $slen; 
                                                        
                            if($this->iCurrentChar=='<'){$this->moveNext();} 
                                                        
                            $text = substr($text,0,($ppp+1)); 
                                                
                            while ($rr = strpos($text, "=")) {//найдем атрибуты
                                                                
                                if($this->iCurrentChar==-1){$this->iCurrentChar="";} 
                                $attrName = $this->skipToBlanksOrEqualsInTag();

                                if ($attrName != "" && $attrName != "/") {
                                                                
                                    $this->skipBlanksInTag();
                                    if ($this->iCurrentChar == "=") {
                                        $this->skipEqualsInTag();
                                        $this->skipBlanksInTag();
                                        $value = $this->readValueInTag();
                
                                        $name .= " ". $attrName . "=\"" . $value . "\"";
                                    }
                                    else {
                                        $name .= " ". $attrName . "=\"" . "" . "\"";
                                    }
                                                                        
                                    if($this->iCurrentChar=='>'){
                                                                         
                                        $name .= '>'; 
                                        $this->iNodeType = NODE_TYPE_TAGBEGINELEMENT;
                                        $this->iNodeName = "TagBeginELEMENT";
                                        $this->iNodeValue = $name;
                                                                                
                                        $this->moveNext();
                                        return true;
                                    } 
                                                                
                                    $ttext = $this->skipToElement();

                                    if(strpos($ttext, "=")){
                         
                                        $sl = strlen($ttext); 
                                        $this->iHtmlTextIndex = $this->iHtmlTextIndex - $sl; 

                                        if($this->iCurrentChar=='<'){$this->moveNext();} 

                                    }
                                    else{
                                        $sll = strlen($ttext); 
                                        $this->iHtmlTextIndex = $this->iHtmlTextIndex - $sll; 

                                        if($this->iCurrentChar=='<'){$this->moveNext();} 

                                        $name .= '>'; 
                                        $this->iNodeType = NODE_TYPE_TAGELEMENT;
                                        $this->iNodeName = "TagELEMENT";
                                        $this->iNodeValue = $name;
                                        return true; 
                                    }
                                }  
                                 
                            }//end while                                                        
 
                            $this->skipEndOfTag();
                           
                            $name .= $text;
                                                        
                            $this->iNodeType = NODE_TYPE_TAGBEGINELEMENT;
                            $this->iNodeName = "TagBeginELEMENT";
                            $this->iNodeValue = $name;
                            return true;  
                        }
                        else{//не найдена '>' 

                            $name .= $text;
                                                        
                            $this->iNodeType = NODE_TYPE_TAGBEGINELEMENT;
                            $this->iNodeName = "TagBeginELEMENT";
                            $this->iNodeValue = $name;
                            return true;
                        }

                    }

                }

            }//end if (!$comment) 

        }
        else {//строка содержит "плохие" символы?
            //эта ветка никогда не выполняется?
            echo(" \r\n Bad simbols in string??? \r\n");  
        }
                
        $this->skipEndOfTag();
        return true;            

    }//end function readTag()
        
    function isValidTagIdentifier ($name) {
                return preg_match ("( /^[A-Za-z0-9_\\-]+$)", $name);
    }
    
    function skipBlanksInTag() {
        return "" != ($this->skipInTag ($this->B_ARRAY));
    }

    function skipToBlanksOrEqualsInTag() {
        return $this->skipToInTag ($this->BOE_ARRAY);
    }

    function skipToBlanksInTag() {
        return $this->skipToInTag ($this->B_ARRAY);
    }

    function skipToBlanksOrSlashInTag() {
        return $this->skipToInTag ($this->BOS_ARRAY);
    }

    function skipEqualsInTag() {
        return $this->skipMaxInTag ("=", 1);
    }

    function readValueInTag() {
        $ch = $this->iCurrentChar;
        $value = "";
        if ($ch == "\"") {
            $this->skipMaxInTag ("\"", 1);
            $value = $this->skipToInTag ("\"");
            $this->skipMaxInTag ("\"", 1);
        }
        else if ($ch == "'") {
            $this->skipMaxInTag ("'", 1);
            $value = $this->skipToInTag ("'");
            $this->skipMaxInTag ("'", 1);
        }                
        else {
            $value = $this->skipToBlanksInTag();
        }
        return $value;
    }

    function setTextIndex ($index) {
        $this->iHtmlTextIndex = $index;
        if ($index >= $this->iHtmlTextLength) {
            $this->iCurrentChar = -1;
        }
        else {
            $this->iCurrentChar = $this->iHtmlText{$index};
        }
    }

    function moveNext() {
        if ($this->iHtmlTextIndex < $this->iHtmlTextLength) {
            $this->setTextIndex ($this->iHtmlTextIndex + 1);
            return true;
        }
        else {
            return false;
        }
    }

    function skipEndOfTag() {
        while (($ch = $this->iCurrentChar) !== -1) {
            if ($ch == ">") {
                $this->moveNext();
                return;
            }
            $this->moveNext();
        }
    }

    function skipInTag ($chars) {
        $sb = "";
        while (($ch = $this->iCurrentChar) !== -1) {
            if ($ch == ">") {
                return $sb;
            } else {
                $match = false;
                for ($idx = 0; $idx < count($chars); $idx++) {
                    if ($ch == $chars[$idx]) {
                        $match = true;
                        break;
                    }
                }
                if (!$match) {
                    return $sb;
                }
                $sb .= $ch;
                $this->moveNext();
            }
        }
        return $sb;
    }

    function skipMaxInTag ($chars, $maxChars) {
        $sb = "";
        $count = 0;
        while (($ch = $this->iCurrentChar) !== -1 && $count++ < $maxChars) {
            if ($ch == ">") {
                return $sb;
            } else {
                $match = false;
                for ($idx = 0; $idx < count($chars); $idx++) {
                    if ($ch == $chars[$idx]) {
                        $match = true;
                        break;
                    }
                }
                if (!$match) {
                    return $sb;
                }
                $sb .= $ch;
                $this->moveNext();
            }
        }
        return $sb;
    }

    function skipToInTag ($chars) {
        $sb = "";
        while (($ch = $this->iCurrentChar) !== -1) {
            $match = $ch == ">";
                        
            if (!$match) {
                for ($idx = 0; $idx < count($chars); $idx++) {
                    if ($ch == $chars[$idx]) {
                        $match = true;
                        break;
                    }
                }
            }
            if ($match) {
                return $sb;
            }
            $sb .= $ch;
            $this->moveNext();
        }
        return $sb;
    }

    function skipToElement() {
        $sb = "";
        while (($ch = $this->iCurrentChar) !== -1) {
            if ($ch == "<") {
                return $sb;
            }
            $sb .= $ch;
            $this->moveNext();
        }
        return $sb;             
    }

    /**
     * Returns text between current position and $needle,
     * inclusive, or "" if not found. The current index is moved to a point
     * after the location of $needle, or not moved at all
     * if nothing is found.
     */
    function skipToStringInTag ($needle) {
        $pos = strpos ($this->iHtmlText, $needle, $this->iHtmlTextIndex);
        if ($pos === false) {
            return "";
        }
        $top = $pos + strlen($needle);
        $retvalue = substr ($this->iHtmlText, $this->iHtmlTextIndex, $top - $this->iHtmlTextIndex);
        $this->setTextIndex ($top);
        return $retvalue;
    }
        
}//end class HTMLParser

function HtmlParser_ForFile ($fileName) { return HtmlParser_ForURL($fileName); }

function HtmlParser_ForURL ($url) {

    $fp = fopen ($url, "r");
    $content = "";
    while (true) {
        $data = fread ($fp, 8192);
        if (strlen($data) == 0) {
            break;
        }
        $content .= $data;
    }
    fclose ($fp);
    return new HtmlParser ($content);
}

function structOfTag($parser){

    $masPrim = array();
    $index = 0; 

    while ($parser->parse()) {
        
        $Arr["struct"] = array(
            "name"=>"", 
            "type"=>"", 
            "value"=>""
        );

        $Arr["struct"]["name"] =  $parser->iNodeName;
        $Arr["struct"]["type"] =  $parser->iNodeType;

        if($parser->iNodeType != NODE_TYPE_DONE ) {
            $Arr["struct"]["value"] = $parser->iNodeValue;
        }

        $masPrim[$index] = $Arr;
        $index++;
    }

    return $masPrim; 
}

        


?>



 

Обновлено 07.10.2015 15:07