2011-05-05 77 views
2

开我想不通为什么这个代码不工作:努力确保HTML标记没有被留在PHP

<?php 
    $text = "<a><li><ul><ol>Hello"; 
    $tags = array('a', 'li', 'ul', 'ol'); 
    $tagcount = count($tags); 
    $i = 0; 

    while ($i < $tagcount) { 
     $opentag = "<".$tags[$i]; 
     $closetag = "</".$tags[$i].">"; 

     if (stripos($text, $opentag)) { 
      $lastopen = strripos($text, $opentag); 
      $lastclose = strripos($text, $closetag); 

      if ($lastopen > $lastclose) { 
       $text = substr($text, 0, $lastopen); 
       echo $tags[$i] . " tag was open. "; 
      } else { 
       echo $tags[$i] . " tag was closed. "; 
     } else { 
      echo $tags[$i] . " tag was not open. "; 
     $i++; 
    } 
?> 

它应该做的是至少表明了$标签阵列中的所有标签是开放的。它的意思是使用substr()来确保没有标签是打开的,但它不起作用。运行此产生:

标记未打开。 li标签已打开。 ul标签未打开。 ol标签未打开。

尽管它们都是开放的。任何帮助将不胜感激。

回答

0

<a>'未打开',因为stripos将返回第一次出现的位置,并且第一次出现位于索引0(其计算结果为false)。

<li>被发现是开放的,因为它的索引不是零。但你截断搜索字符串,以便下一次迭代<ul>在零指数发现...

改变,如果对你的stripos($text, $opentag) === false,看看是否有可以让你找到a标记为打开。你必须弄清楚如何处理substr(...),因为我认为你的业务逻辑很可能决定这一点。

0

看来你的逻辑是有缺陷的:strripos回报false如果没有找到针头所以在你的内心if声明你正在测试如果一个数比false更大。

为了您的外if语句,你需要测试假:

if (stripos($text, $opentag) !== false) { 
    // found at position 0 or more... 

你内心if应该是这样的:

if (($lastclose !== false) && ($lastopen > $lastclose)) { 
0

下面是使用正则表达式的作品为例:

$text = "<a><li><ul><ol>Hello"; 
    $tags = array('a', 'li', 'ul', 'ol'); 
    $tagcount = count($tags); 
    $i = 0; 
    $matches = array(); 
    foreach ($tags as $tag) 
    { 
    $closed = preg_match_all("/<\/".$tag.">/i", $text, $matches); 
    $open = preg_match_all("/<".$tag.">/i", $text, $matches); 

    if ($open == 0) 
    { 
     echo $tag." was not opened, "; 
    } 
    else if ($open > $closed) 
    { 
     echo $tag." was left open, "; 
    } 
    else 
    { 
     echo $tag." was closed properly, "; 
    } 
} 
0

解析HTML是非琐事的我有一些很好的图书馆为你做这项工作。 Tidy库自PHP 5起可用,可用于解析和整理HTML片段,或完成页面输出。有一个很好的article on devzone,它显示了如何使用它,包括如何将它与output buffering相结合。

对于您发布的代码,您不应该在if语句中使用strpos。引述PHP手册:

Warning: This function may return Boolean FALSE, but may also return a non-Boolean value which evaluates to FALSE, such as 0 or "" . . . Use the === operator for testing the return value of this function.

所以要测试一个字符串是不是在字符串中发现,这样做:

if(strpos($haystack, $needle) === FALSE) 

,并测试一个子找到:

if(strpos($haystack, $needle) !== FALSE) 

但是我确实会建议使用预先存在的库进行HTML操作或验证,尤其是在安全敏感的情况下(例如反XSS)。