php版getElementsByTagName , php版根据标签名获取 标签节点列表.模拟javascript的getElementsByTagName函数
2013-05-06 16:25
555 查看
新鲜出炉,昨天周末写的 php版getElementsByTagName模拟javascript的getElementsByTagName , 根据标签名获取 标签列表.(多层嵌套也正常匹配)
以下凑足200字....
/*
* 功能: php版getElementsByTag , 根据标签名获取 标签列表.(多层嵌套也正常匹配)
* 参数:
$str 被查找的字符串;
$start_tag 开始标记;
$close_tag 关闭标记;
[可选] $tag_slashe 加在 标记 之前, 用于转义的字符(目的是防止混淆正常字符和标记), 默认false;
[可选] $begin_pos , 用于指定开始查找的位置, 默认0 . 该参数在模仿类似js的语法: obj.getElementsByTagName() , 查找指定对象之下的标签列表时非常有用处;
[可选] $end_pos , 用于指定结束位置, 默认0 .
* 返回: 查找成功返回数组列表, 查找没有结果则返回false.
* 作者: 王奇疏
*/
测试数据
如果标签正常闭合,就能正常正确地匹配节点,测试结果如下图:
--------------
2.如果标签没有闭合,提示错误
--------------
以下凑足200字....
/*
* 功能: php版getElementsByTag , 根据标签名获取 标签列表.(多层嵌套也正常匹配)
* 参数:
$str 被查找的字符串;
$start_tag 开始标记;
$close_tag 关闭标记;
[可选] $tag_slashe 加在 标记 之前, 用于转义的字符(目的是防止混淆正常字符和标记), 默认false;
[可选] $begin_pos , 用于指定开始查找的位置, 默认0 . 该参数在模仿类似js的语法: obj.getElementsByTagName() , 查找指定对象之下的标签列表时非常有用处;
[可选] $end_pos , 用于指定结束位置, 默认0 .
* 返回: 查找成功返回数组列表, 查找没有结果则返回false.
* 作者: 王奇疏
*/
<?php echo '<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />'; /* * 功能: php版getElementsByTag , 根据标签名获取 标签列表.(多层嵌套也正常匹配) * 参数: $str 被查找的字符串; $start_tag 开始标记; $close_tag 关闭标记; [可选] $tag_slashe 加在 标记 之前, 用于转义的字符(目的是防止混淆正常字符和标记), 默认false; [可选] $begin_pos , 用于指定开始查找的位置, 默认0 . 该参数在模仿类似js的语法: obj.getElementsByTagName() , 查找指定对象之下的标签列表时非常有用处; [可选] $end_pos , 用于指定结束位置, 默认0 . * 返回: 查找成功返回数组列表, 查找没有结果则返回false. * 作者: 王奇疏 */ function getElementsByTag( $str , $start_tag , $close_tag , $tag_slashe=false , $begin_pos=0 , $end_pos=0 ) { $list = array( ); $start = $begin_pos;// 临时存储字符位置 $end = $end_pos; $start_pos = $close_pos = 0; // 每一对标记的起止位置 $stack = array(); // 一个数组, 用来借助栈的作用保存上一次循环的数据. $s_len = strlen( $start_tag ); // 标记本身的长度 $c_len = strlen( $close_tag ); $slashe_ord = ord( $tag_slashe ); // 转义符 while( false !== ( $start = stripos( $str , $start_tag , $start ) ) ) { $i = 0; // 标记 计数器 $j = 1024; // 最大循环计数器 , 防死循环 $start_pos = $start; // 初始化每对标记的起止位置 $close_pos = $start_pos + $s_len; // (close_tag的开始位置应在start_tag之后) $stack = array(); while ( $j > 0 ){ // 一次搜索两种标记: $start_tag , $close_tag if ( $start_pos > $start ) { $start_pos = stripos( $str , $start_tag , $start_pos ); } $close_pos = stripos( $str , $close_tag , $close_pos ); // 如果 找到的标记 的前面一个字符是转义符 , 则再重新搜索一次. if ( false !== $start_pos && $slashe_ord === ord( $str[ $start_pos - 1 ] ) ) { $start_pos = stripos( $str , $start_tag , $start_pos + $s_len ); } if ( false !== $close_pos && $slashe_ord === ord( $str[ $close_pos - 1 ] ) ) { $close_pos = stripos( $str , $close_tag , $close_pos + $c_len ); } // 把 关闭标记的位置 存进栈内, 保持只存2条. if ( $j === 1024 ) { $stack[] = $close_pos; // (第1次多存1条) } $stack[] = $close_pos; // 开始标记 大于 上一个关闭标记, if ( $start_pos > ( $prev = array_shift( $stack ) ) ) { $prev += $c_len; break; } // 找不到开始标签时, 从哪开头? elseif ( false === $start_pos ) { $prev += $c_len; break; } // 找不到闭合的标签时, 从哪开头?怎么处理? elseif ( false === $close_pos ) { show_match_error( $str , $start , $start_tag , $close_tag ); return false; } else { $start_pos += $s_len; $close_pos += $c_len; } --$j; } if ( $j == 0 ) { show_match_error( $str , $start , $start_tag , $close_tag ); return false; } $list[] = substr( $str , $start , $prev - $start ); $start = $prev; } return $list; } // 仅仅用于显示匹配错误信息的函数 function show_match_error( $str , $sub_start , $start_tag , $close_tag ) { $count_line = substr( $str , 0 , $sub_start ); $count_line = substr_count( $count_line , PHP_EOL ) + 1; trigger_error( '<div style="padding: 10px;font-family:tahoma;font-size:12px; border:1px solid #c1c1c1; "><strong>出现标签未闭合的错误:</strong><br /><br />程序设定的<br />开始标记是: <font color="red">'.htmlspecialchars( "{$start_tag} " ).'</font> <br />闭合标记是: <font color="red">'.htmlspecialchars( "{$close_tag} " ).'</font> <br /><font color="red"><br />现检查到有一个标记没有闭合,不符合xhtml规范,已经停止匹配.</font><br /><br />未闭合标记的位置在原文中从<font color="red">第'.$count_line.'行</font>开始 , 在周围缺少闭合标签. <br />(<font color="red">第'.$count_line.'行</font>)大约是从以下字符开始, 请查看您原来的数据,检查标记是否闭合完整: <br />"<pre>'.htmlspecialchars( substr( $str , $sub_start , 80 ) ).'</pre> "</div>' ); }
测试数据
<?php // 测试数据:----------- $str = <<<EOF <html> <head> <title> 测试模板文件 </title> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> </head> <body> <br /> 1.变量:<br /> $title.<br /> \$title2这里的变量对$标记使用了转义符号\$,所以不会被当成php变量\$title2来解释<br /><br /> 1.2<br /> 链式变量:$shop->getobj()->show(2)<br /><br /> 2.分支语句<br /> 欢迎~if( $user == 'admin' ){ 管理\~\}员hhhhhhhhhhhhh}else{ : echo $user; }~登陆<br /><br /><br /> ~if( $user == 'admin' ){ : echo 'set first char to : , then you can write php syntax here.'; var_dump( 'hello php syntax.' ); if( $ty ){ echo 'good.........'; } else{ echo 'bad..........'; } if( $ty ){ echo 'good.........'; } else{ echo 'bad..........'; } if( $ty ){ echo 'good.........'; if( $ty ){ echo 'good.........'; } else{ echo 'bad..........'; } } else{ echo 'bad..........'; } } else(){ no : , you can write html here . \} } ~<br /><br /><br /> 3.函数标签<br /> 直接调用函数标签,作用是输出函数:<var_dump( 'abc' )><br /><br /> 4.循环标签.<br /> <loop $array $i=0><br /> ·[<a href="#">$sort</a>] <a href="#author">$user </a> : $title. <img src="./yes.jpg" alt="图文提示" /> - $time<br /> </loop><br /><br /> <li> <li> <li> </li> </li> </li> <li> <li> </li> </li> <div id="test"> <div> <div> aaaaa </div> <div> <div> <div> <div> bbb <div> .ccc. </div> </div> </div> </div> </div> <div> dddddd </div> <div> eeeeeeeeee </div> </div> <div> ffff </div> ggggggggggggg </div> <div>h</div> <div>i</div> <div></div> <div> </div> <div>1</div> <div>2</div> <div> </div> EOF; $test = getElementsByTag( $str , '<div' , '</div>' , '\\' ); // $test = getElementsByTag( $str , '{' , '}' , '\\' ); // $test = getElementsByTag( $str , '~if' , '~' , '\\' ); // $test = getElementsByTag( $str , '<li' , '</li>' , '\\' ); echo '<pre>';print_r( $test );echo '</pre>';exit;
如果标签正常闭合,就能正常正确地匹配节点,测试结果如下图:
--------------
2.如果标签没有闭合,提示错误
--------------
相关文章推荐
- getElementsByTagName是根据标签名获取元素
- 【JavaScript】利用getElementsByTagName与getElementsByName改进原生态兼容IE6标签页
- getElementsByClassName函数实现获取指定类名的子元素列表
- javascript对于dom的操作--得到兄弟节点 && getElementsByTagName使用方法
- 【JavaScript】修正IE下document.getElementsByName无法获取DIV标签,兼容IE FF的ByName方法
- Javascript下获取对象引用的两种方法之getElementsByTagName
- javascript对于dom的操作--得到兄弟节点 && getElementsByTagName使用方法
- Js基础学习之 -- DOM兼容 根据标签、类名获取节点函数封装
- js中获取类名的函数getElementsByClassName()
- javascript的getComputedStyle方法获取节点的计算后的CSS样式
- 获取HTML元素3个方法:document.getElementsByName()、document.getElementById()、document.getElementsByTagName()
- getNextElement( )函数——获取下一个特定的元素节点
- 关于javascript解析xml文件时找不到元素getElementsByTagName()
- php的curl函数模拟post、get数据提交,速度非常慢的处理办法
- PHP获取接口数据(模拟Get)
- 获取HTML元素3个方法:document.getElementsByName()、document.getElementById()、document.getElementsByTagName()
- [PHP] GD库(三):获取图像信息 getimagesize 函数
- php使用get_class_methods()函数获取分类的方法
- PHP根据身份证号码验证、获取星座、生肖和性别函数
- 根据原生JS封装函数,根据传递的选择器查找对应的元素以及解决getElementsByClassName() 兼容问题