<?php
header("Content-Type: text/html; charset=utf-8");
class html_parser{
private $article='';
private $size_article='';
private $code_obj=array();
private $special_tag=array('style','script','title','texta rea','nobody','canvas') ;
/////////////////////////////////////////
public $key_is_start_tag='is';
public $key_is_extra_value='ix';
public $key_is_end_tag='ie';
public $key_is_content='ic';
public $key_value='v';
public $key_is_attribute='ia';
public $key_attribute='av';
/////////////////////////////
function __construct(){
}
private function find_sub_case($sub='',$start=0){
$str=$this->article;
$size_sub=strlen($sub);
$size_str=$this->size_article;
for($i=$start;$i<$size_str;$i++){
$j=0;
$k=$i;
while($j<$size_sub&&strcasecmp($sub[$j],$str[$k])==0){
$j++;
$k++;
}
if($j==$size_sub){
return $k;
}
}
return -1;
}
private function atrributes_str($start_index=0,&$attributes_str_res =''){
//start index must be ' ' or >'>'
$div_sign_end_tag=0;
$attributes_str_res='';
$attributes_str='';
$i=$start_index;
$end_of_attribute=$i;
$article=$this->article;
$size_article=$this->size_article;
$attributes=array();
$end_of_tag=0;
if($i>=$size_article){
return $i;
}
if(!(ord($article[$i])<=32||$article[$i]=='>')){
return $i;
}
while($i<$size_article){
if($article[$i]==">"){
//$i++;
$attributes_str_res=$attributes_str;
return $i;
break;
}elseif($i+1<=$size_article&&$article[$i]=='/'&&$article[$i+1]=='>'){
$i++;
$attributes_str_res=$attributes_str.' /';
return $i;
}
if($article[$i]=='=' &&ord($article[$i-1])>32){
$j=$i-1;
$k=$j;
while($j>=0){
if((($j-1)>=0&&ord($article[$j-1])<=32)||($j-1)<=$end_of_attribute){
break;
}
$j--;
}
if(isset($attribute_name)){
unset($attribute_name);
}
if($j<$k){
$attribute_name=substr($article,$j,$k-$j+1);
}elseif($j==$k){
$attribute_name=$article[$j];
}
$i++;
while($i<$size_article&&ord($article[$i])<=32){
$i++;
}
$attribute_value='';
if($article[$i]=="'"){
$i++;
while($i<$size_article){
if($article[$i]=="'"){
$end_of_attribute=$i;
break;
}
$attribute_value.=$article[$i];
$i++;
}
}elseif($article[$i]=='"'){
$i++;
while($i<$size_article){
if($article[$i]=='"'){
$end_of_attribute=$i;
break;
}
$attribute_value.=$article[$i];
$i++;
}
}else{
while($i<$size_article&&ord($article[$i])<=32){
$i++;
}
while($i<$size_article&&ord($article[$i])>32){
if($article[$i]=='>'){
$end_of_tag=1;
break;
}elseif($i+1<=$size_article&&$article[$i]=='/'&&$article[$i+1]=='>'){
$i++;
$div_sign_end_tag=1;
$end_of_tag=1;
break;
}else{
$attribute_value.=$article[$i];
$i++;
}
}
}
if(isset($attribute_name)&&$attribute_name){
$attribute_name=strtolower($attribute_name);
$attribute_name_exist=0;
for($t=0;$t<count($attributes);$t+=2){
if($attributes[$t]==$attribute_name){
$attribute_name_exist=1;
break;
}
}
if($attribute_name_exist==0){
$attributes[]=$attribute_name;
$attributes[]=$attribute_value;
$disallowd_attri=0;
$attributes_str.=' ';
for($c=0;$c<strlen($attribute_name);$C++){
$attributes_str.=$attribute_name[$c];
}
$attributes_str.='="'.$attribute_value.'"';
}
unset($attribute_name);
}
}
if($end_of_tag){
break;
}
$i++;
}
if($div_sign_end_tag){
$attributes_str.=' /';
}
$attributes_str_res=$attributes_str;
return $i;
}
private function attribute_parse($start_index=0,&$attributes_arr_re s=array()){
//start index must be ' ' or >'>'
$attributes_arr_res=array();
$i=$start_index;
$end_of_attribute=$i;
$article=$this->article;
$size_article=$this->size_article;
$temp_attributes=array();
$attributes=array();
$end_of_tag=0;
if($i>=$size_article){
return $i;
}
if(!(ord($article[$i])<=32||$article[$i]=='>')){
return $i;
}
while($i<$size_article){
if($article[$i]==">"){
//$i++;
$attributes_arr_res=$attributes;
return $i;
break;
}
if($article[$i]=='=' &&ord($article[$i-1])>32){
$j=$i-1;
$k=$j;
while($j>=0){
if((($j-1)>=0&&ord($article[$j-1])<=32)||($j-1)<=$end_of_attribute){
break;
}
$j--;
}
if(isset($attribute_name)){
unset($attribute_name);
}
if($j<$k){
$attribute_name=substr($article,$j,$k-$j+1);
}elseif($j==$k){
$attribute_name=$article[$j];
}
$i++;
while($i<$size_article&&ord($article[$i])<=32){
$i++;
}
$attribute_value='';
if($article[$i]=="'"){
$i++;
while($i<$size_article){
if($article[$i]=="'"){
$end_of_attribute=$i;
break;
}
$attribute_value.=$article[$i];
$i++;
}
}elseif($article[$i]=='"'){
$i++;
while($i<$size_article){
if($article[$i]=='"'){
$end_of_attribute=$i;
break;
}
$attribute_value.=$article[$i];
$i++;
}
}else{
while($i<$size_article&&ord($article[$i])<=32){
$i++;
}
while($i<$size_article&&ord($article[$i])>32){
if($article[$i]=='>'){
$end_of_tag=1;
break;
}
$attribute_value.=$article[$i];
$i++;
}
}
if(isset($attribute_name)&&$attribute_name){
$attribute_name=strtolower($attribute_name);
$attribute_name_exist=0;
for($t=0;$t<count($temp_attributes);$t+=2){
if($temp_attributes[$t]==$attribute_name){
$attribute_name_exist=1;
break;
}
}
if($attribute_name_exist==0){
$temp_attributes[]=$attribute_name;
$temp_attributes[]=$attribute_value;
$attributes[strtolower($attribute_name)]=$attribute_value;
}
unset($attribute_name);
}
}
if($end_of_tag){
break;
}
$i++;
}
$attributes_arr_res=$attributes;
return $i;
}
public function parse($article=''){
$this->article=$article;
$this->size_article=strlen($article);
$i=0;
$size_article=$this->size_article;
$temp_res='';
$res_arr=array();
while($i<$size_article){
if($i+1<$size_article&&$article[$i]=='<'&&ctype_alpha($article[$i+1])){
if(strlen($temp_res)){
$res_arr[]=array($this->key_is_content=>1,$this->key_value=>$temp_res);
$temp_res='';
}
$f_index_of_start_tag=$i+1;
$tag_name='';
$attribute_exist=1;
$i++;
while($i<$size_article&&ord($article[$i])>32){
if($article[$i]=='>'){
$attribute_exist=0;
$i++;
break;
}
$tag_name.=$article[$i];
$i++;
}
$tag_name=strtolower($tag_name);
$special_tag=0;
for($c=0,$count_special_tag=count($this->special_tag);$c<$count_special_tag;$C++){
if(strcasecmp($tag_name,$this->special_tag[$c])==0){
$special_tag=1;
$res='';
break;
}
}
if($special_tag){
$attributes_arr=array();
if($attribute_exist){
$i=$this->attribute_parse($i,$attributes_arr);
$i++;
}
$l_index_of_start_tag=$i;
$latest_find_index=$this->find_sub_case('</'.$tag_name,$l_index_of_start_tag);
if($latest_find_index==-1){
$i=$size_article;
$latest_find_index=$size_article;
$tag_value=(substr($article,$l_index_of_start_tag, $latest_find_index-$l_index_of_start_tag-1));
} else{
$i=$latest_find_index;
$tag_value=(substr($article,$l_index_of_start_tag, $latest_find_index-$l_index_of_start_tag-strlen("</$tag_name")));
$i=$this->attribute_parse($i,$temp_arr);
$i++;
}
if($attributes_arr){
// $res_arr[]=array('type'=>'start','value'=>strtolower($tag_na me),'attributes'=>$attributes_arr);
$res_arr[]=array($this->key_is_start_tag=>1,$this->key_value=>strtolower($tag_name),$this->key_is_attribute=>1,$this->key_attribute=>$attributes_arr);
}else{
// $res_arr[]=array('type'=>'start','value'=>strtolower($tag_na me));
$res_arr[]=array($this->key_is_start_tag=>1,$this->key_value=>strtolower($tag_name));
}
// $res_arr[]=array('type'=>'etext','value'=>$tag_value);
$res_arr[]=array($this->key_is_extra_value=>1,$this->key_value=>$tag_value);
//$res_arr[]=array('type'=>'end','value'=>strtolower($tag_name ));
$res_arr[]=array($this->key_is_end_tag=>1,$this->key_value=>strtolower($tag_name));
}else{
if($attribute_exist){
$attributes_arr=array();
$i=$this->attribute_parse($i,$attributes_arr);
$i++;
// $res_arr[]=array('type'=>'start','value'=>strtolower($tag_na me),'attributes'=>$attributes_arr);
$res_arr[]=array($this->key_is_start_tag=>1,$this->key_value=>strtolower($tag_name),$this->key_is_attribute=>1,$this->key_attribute=>$attributes_arr);
// $temp_res.='<'.$tag_name.$attributes_str.'>';
}else{
// $temp_res.='<'.$tag_name.'>';
$res_arr[]=array($this->key_is_start_tag=>1,$this->key_value=>strtolower($tag_name));
}
}
}
elseif($i+2<$size_article&&$article[$i]=='<'&&$article[$i+1]=='/'){
if(strlen($temp_res)){
// $res_arr[]=array('type'=>'text','value'=>$temp_res);
$res_arr[]=array($this->key_is_content=>1,$this->key_value=>$temp_res);
$temp_res='';
}
if(ctype_alpha($article[$i+2])) {
$f_index_of_start_tag=$i+2;
$end_tag_name='';
$attribute_exist=1;
$i+=2;
while($i<$size_article&&ord($article[$i])>32){
if($article[$i]=='>'){
$attribute_exist=0;
$i++;
break;
}
$end_tag_name.=$article[$i];
$i++;
}
if($attribute_exist){
$attributes_str='';
$i=$this->atrributes_str($i,$attributes_str);
$i++;
if(1){
// $temp_res.='</'.$end_tag_name.''.'>';
// $res_arr[]=array('type'=>'end','value'=>strtolower($end_tag_ name));
$res_arr[]=array($this->key_is_end_tag=>1,$this->key_value=>strtolower($end_tag_name));
}
}else{
if(1){
//$temp_res.='</'.$end_tag_name.'>';
$res_arr[]=array($this->key_is_end_tag=>1,$this->key_value=>strtolower($end_tag_name));
}
}
} else{
while($i<$size_article){
if($article[$i]=='>'){
$temp_res.=$article[$i];
$i++;
break;
}
$temp_res.=$article[$i];
$i++;
}
if(strlen($temp_res)){
// $res_arr[]=array('type'=>'etext','value'=>$temp_res);
$res_arr[]=array($this->key_is_extra_value=>1,$this->key_value=>$temp_res);
$temp_res='';
}
}
}
elseif($i+1<$size_article&&$article[$i]=='<'&&$article[$i+1]=='!'){
if(strlen($temp_res)){
// $res_arr[]=array('type'=>'text','value'=>$temp_res);
$res_arr[]=array($this->key_is_content=>1,$this->key_value=>$temp_res);
$temp_res='';
}
while($i<$size_article){
if($article[$i]=='>'){
$temp_res.=$article[$i];
$i++;
break;
}
$temp_res.=$article[$i];
$i++;
}
if(strlen($temp_res)){
// $res_arr[]=array('type'=>'etext','value'=>$temp_res);
$res_arr[]=array($this->key_is_extra_value=>1,$this->key_value=>$temp_res);
$temp_res='';
}
}
else{
$temp_res.=$article[$i++];
}
// $i++;
}
if(strlen($temp_res)){
// $res_arr[]=array('type'=>'text','value'=>$temp_res);
$res_arr[]=array($this->key_is_content=>1,$this->key_value=>$temp_res);
$temp_res='';
}
$this->code_obj= $res_arr;
return 1;
}
public function get_code_obj(){
return $this->code_obj;
}
} // end class
$html_parser=new html_parser();
$html_parser->parse('<div style="text-align: left;"><div style="margin-right:40px"><u>مثلا</u> این <strong>متن</strong> اینجوری <em>ذخیره</em> شده:</div></div>') ;
$html_code_obj=($html_parser->get_code_obj()) ;
$size_html_code_obj=count($html_code_obj);
$html_final="";
for($i=0;$i<$size_html_code_obj;$i++)
{
$currect_node=$html_code_obj[$i];
if(isset($currect_node[$html_parser->key_is_start_tag]))
{
$node_attributes=array();
$tag_name=$currect_node[$html_parser->key_value];
$html_final.="<".$currect_node[$html_parser->key_value];
if(isset($currect_node[$html_parser->key_is_attribute]))
{
$node_attributes=$currect_node[$html_parser->key_attribute];
foreach($currect_node[$html_parser->key_attribute] as $attribute_key=>$attribute_value)
{
if($attribute_key=='style')
{
continue;
}
$html_final .=" " . $attribute_key .'=' ;
if(strstr($attribute_value,"'"))
{
$html_final .= '"'. $attribute_value .'"' ;
}elseif(strstr($attribute_value,'"'))
{
$html_final .= "'". $attribute_value ."'" ;
}else
{
$html_final .= '"'. $attribute_value .'"' ;
}
}
$html_final .= ">";
}else
{
$html_final .= ">";
}
}
elseif(isset($currect_node[$html_parser->key_is_content]))
{
$html_final .= $currect_node[$html_parser->key_value];
}
elseif(isset($currect_node[$html_parser->key_is_end_tag]))
{
$html_final .="</". $currect_node[$html_parser->key_value]."/>";
}
}
var_dump($html_final) ;