Каждая программа имеет свою пред-историю. Это то, что побудило написать ее.
Я знаком с несколькими 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;
}
?>
|