如何验证打开和关闭标签的数量?

时间:2011-04-18 14:46:24

标签: php html

我想为每个"/<[a-z0-9]+>/i"做一个preg_count,然后计算是否与封闭标签存在相同的数字,即:"/</[a-z0-9]+>/i"

但我不太确定。你如何计算所有打开的标签并检查是否存在所有已关闭的标签?

聚苯乙烯。我不需要检查属性和xml />单个关闭标记。我只需要依靠普通的简单html标签

由于

4 个答案:

答案 0 :(得分:1)

验证HTML的正确方法是使用HTML解析器。使用Regexes处理HTML是非常错误的 - 请参阅RegEx match open tags except XHTML self-contained tags

答案 1 :(得分:1)

我写了这个方便的功能。我认为如果我在一个preg_match_all中搜索两个打开/关闭的标签可能会更快但是因为它更具可读性:

<?php

//> Will count number of <[a-z]> tag and </[a-z]> tag (will also validate the order)
//> Note br should be in the form of <br /> for not causing problems
function validHTML($html,$checkOrder=true) {
    preg_match_all( '#<([a-z]+)>#i' , $html, $start, PREG_OFFSET_CAPTURE );
    preg_match_all( '#<\/([a-z]+)>#i' , $html, $end, PREG_OFFSET_CAPTURE );
    $start = $start[1];
    $end = $end[1];

    if (count($start) != count($end) )
        throw new Exception('Check numbers of tags');

    if ($checkOrder) { 
        $is = 0;
        foreach($end as $v){
            if ($v[0] != $start[$is][0] || $v[1] < $start[$is][1] )
                throw new Exception('End tag ['.$v[0].'] not opened');

            $is++;
        }
    }

    return true;
}

//> Usage::

try {
    validHTML('<p>hello</p><li></li></p><p>');

} catch (Exception $e) { 
    echo $e->getMessage();
}

注意如果您需要捕获偶数h1或任何其他带有数字的标记,您需要在preg模式中添加0-9

答案 2 :(得分:0)

我的案例

function checkHtml($html) {
    $level = 0;
    $map = []; 
    $length = strlen($html);
    $open = false;
    $tag = '';        
    for($i = 0; $i < $length; $i ++) {
        $c = substr($html, $i, 1);

        if($c == '<') {
            $open = true;
            $tag = '';
        }  else if($open && ($c == '>' || ord($c) == 32)) {
            $open = false;
            if(in_array($tag, ['br', 'br/', 'hr/', 'img/', 'hr', 'img'])) {
                continue;
            }
            if(strpos($tag, '/') === 0) {
                if(!isset($map[$tag.($level-1)])) {
                    return false;
                }
                $level --;
                unset($map[$tag.$level]); 
            } else {
                $map['/'.$tag.$level] = true;
                $level ++;
            } 
        } else if($open) {
           $tag .=  $c;
        }
    }
    return $level == 0;
}

答案 3 :(得分:-1)

好的,一个解决方案是:

function open_tags($page)
{
    $arr=array();
    $page // your html/xml/somthing content
       $i=0; 
    while ($i<strlen($page))
        {

            $i=strpos($page,'<',$i); //position of starting the tag
            $end=strpos($page,'>',$i); //position of ending the tag
            if(strpos($page,'/')<$end) //if it's an end tag
             {
                if (array_pop($arr)!=substr($page,$i,$end-$i)); // pop the last value inserted into the stack, and check if it's the same as this one
                  return FALSE;
             }

            else
            {
              array_push($arr,substr($page,$i,$end-$i)); // push the new tag value into the stack
            }

        }

return $arr;
}

这将按顺序返回打开的标签,如果错误则返回false。

修改

function open_tags($page)
{
    $arr=array();
    $page // your html/xml/somthing content
       $i=0; 
    while ($i<strlen($page))
        {

            $i=strpos($page,'<',$i); //position of starting the tag
            $end=strpos($page,'>',$i); //position of ending the tag
            if($end>strpos($page,'<',$i))
                return false;
            if(strpos($page,'/')<$end) //if it's an end tag
             {
                if (array_pop($arr)!=substr($page,$i,$end-$i)); // pop the last value inserted into the stack, and check if it's the same as this one
                  return FALSE;
             }

            else
            {
              array_push($arr,substr($page,$i,$end-$i)); // push the new tag value into the stack
            }

        }

return $arr;
}