php版getElementById , 栈的查找匹配,html标签多层嵌套也很ok

来自:互联网
时间:2018-08-05
阅读:

功能: 成对匹配html标签对, 跟JavaScript的$.getElementById() 方法 一样.多层嵌套也很ok

不使用递归方法,而是利用栈的知识,通过位置回退方法、顺序进行匹配关闭标签。eg:

<?php
$str = '
    <div id="left" class="*xxx" style="float: left;width:520px; height: 200px; " >
        <div class="new_model1">
            <p> <a href="#" >title</a> </p>
        </div>
        <div class="new_model2">
            <p> <a href="#" >title</a> </p>
        </div>
        <div>
            dsss
            <div>dsss</div>    
            <div>dsss</div>    
            <div>dsss</div>    
        </div>    
        <!-- 多层嵌套 -->
        <div class="000"><div class="000"><div class="000"><div class="000"><div class="000"></div></div></div></div><div class="000"></div></div>
    </div>
    <div class="111"><div class="111"><div class="111"><div class="111"><div class="111"></div></div></div></div><div class="111"></div><div class="111"><div class="111"><div class="111"></div></div></div><div class="111"></div></div>
';
var_dump( getElementById( $str , 'left' ) );

输出结果:

<div id="left" class="*xxx" style="float: left;width:520px; height: 200px; " >
           ...
        <!-- 多层嵌套 -->
        <div class="000"><div class="000"><div class="000"><div class="000"><div class="000"></div></div></div></div><div class="000"></div></div>
    </div>

代码:

<?php
/*
* 功能: 成对匹配html标签对, 跟javascript的$.getElementById() 方法 一样.
* 实现方法: 成对匹配html标签对(多层嵌套也能完整匹配)
            ( 没有用到递归, 而是通过位置回退方法、顺序进行匹配 )
* 参数: 
    @string: $content: 输入内容; 
    @string: $id 标签的id; 
    @string: $return_type   设定返回值的类型,
                可选返回 'endpos'(结束位置) 或者 'substr'(截取结果). 
* 返回:  数字 或 字符串 , 取决于 $return_type的设置. 
* @author: 王奇疏 
*/
function getElementById( $content , $id , $return_type='substr' ) {
// 匹配唯一标记的标签对
    if ( preg_match( '@<([a-z]+)[^>]*id=["']?'.$id.'["']?[^>]*>@i' , $content , $res ) ){
        
        $start = $next_pos = strpos( $content , $res[0] );
        ++$next_pos;
        $start_tag = '<'.$res[1]; // 开始标签
        $end_tag = '</'.$res[1].'>'; // 结束标签
        $i = 1;
        $j = 0; // 防死循环      
        
        // 只要计数大于0, 就继续查,查到计数器为0为止, 就是最终的关闭标签.
        while ( $i > 0 && $j < 1024 ){
             $p_start = stripos( $content , $start_tag , $next_pos );
            $p_end = stripos( $content , $end_tag , $next_pos );
            if ( false === $p_start && false !== $p_end ){// 如果找不到开始标签,但还有结束标签,那么开始位置为结束标签位置+1,结束循环
                $next_pos = $p_end + 1;
                break;
           }            
            // 如果
            elseif ( $p_start > $p_end ){// 当开始标签的位置,大于结束标签的位置,开始位置为结束标签位置+1,直到 i 为0,结束循环
                $next_pos = $p_end + 1;
                --$i;
            }
            else{// 前面条件未符合时,每一次循环,开始位置都为 开始标签位置+1
                $next_pos = $p_start + 1;
                ++$i;
            }
        }
        if ( $j == 1024 ){
            exit( '调用getElementById时出现错误::<font color="red">您的标签'.htmlspecialchars( "{$start_tag} id='{$id}'>" ).' 在使用时根本没有闭合,不符合xhtml,系统强制停止匹配</font>.' ); 
        }
        // 返回结果
        if ( 'substr' == $return_type ){
            return substr( $content , $start , $next_pos-$start + strlen( $end_tag ) );
        }
        elseif ( 'endpos' == $return_type ){
            return $next_pos + strlen( $end_tag ) - 1 ;
        }
        else{
            return false;
        }
    }
    else{
        return false;
    }
}
返回顶部
顶部