计数开始和结束html标签


Count start and end html tags

我正在寻找一种方法来计数html标签在html块使用php。这可能不是一个完整的网页与doctype正文标签等。

例如:

如果我有这样的东西

$string = "
<div></div>
<div style='blah'></div>
<p>hello</p>
<p>its debbie mcgee
<p class='pants'>missing p above</p>
<div></div>";

我想把它传递给一个标签名称为

的函数

CheckHtml($string, 'p');

,我想让它告诉我打开<p>标签的数量和关闭p标签</p>的数量。除此之外,我不希望它做任何花哨的事情(没有鬼鬼祟祟地试图修复它)。

我已经尝试了字符串计数与开始标签,如<p,但它可以很容易地找到类似的东西,并返回错误的结果。

我看了看DOMDocument,但它似乎不计算关闭标签,总是期望<html>标签(虽然我可以解决这个问题)。

关于使用什么有什么建议吗?

要获得准确的计数,不能使用字符串匹配或正则表达式,因为用正则表达式解析HTML存在众所周知的问题

也不能使用标准解析器的输出,因为那是一个由元素组成的DOM, HTML中关于标记的所有信息都被丢弃了。即使对于有效的HTML,也可以推断出结束标签,甚至可以推断出一些开始标签(例如HTML, head, body, tbody)。此外,像收养代理算法这样的事情可能会导致HTML标记中的元素数量超过标签数量。例如,<b><i></b>x</i>将导致DOM中有两个i元素。与此同时,不能与开始标签匹配的结束标签被简单地丢弃,实际上出现在错误位置的开始和结束标签也可能被丢弃。(如<caption>不在<table>中,<legend>不在<fieldset>中)

我认为你可以可靠地做到这一点的唯一方法是:

有一个用于解析HTML的开源PHP库叫做html5lib。

在这里,有一个名为Tokenizer.php的文件,在该文件的末尾有一个名为emitToken的函数。此时,解析器已经完成了找出所有HTML怪异之处的所有工作¹,并且$token参数包含关于已识别的标记类型的所有信息,包括开始和结束标记。

您可以使用库并修改它,以便它在该点计算开始和结束标记令牌,然后在解析过程结束时将这些总数公开给应用程序代码。


¹:也就是说,它已经计算出了与你的计算问题相关的奇怪之处。它还没有开始弄清楚树结构的奇怪之处。

您可以使用substr_count()返回针子字符串在干草堆$string中出现的次数。

$open_tag_count = substring_count( $string, '<p' );
$close_tag_count = substring_count( $string, '</p>' );

请注意'<param和<pre,因此您可能需要修改搜索以处理两种不同的特定情况:>

$open_tag_count_without_attributes = substring_count( $string, '<p>' );
$open_tag_count_with_attributes = substring_count( $string, '<p ' );
$open_tag_count = $open_tag_count_without_attributes + $open_tag_count_with_attributes;

您可能还希望考虑使用[preg_match()][1]。使用正则表达式解析HTML具有相当多的缺陷,因此请谨慎使用。

substr_count似乎是个不错的选择。

编辑:你必须使用preg_match然后

我还没有测试过,但是,为了一个想法…

function checkHTML($string,$htmlTag){
  $openTags = preg_match('/<'.$htmlTag.''b[^>]*>',$string);
  $closeTags = preg_match('/<'/'.$htmlTag.'>/',$string);
  return array($openTags, $closeTags);
}
$numberOfParagraphTags = checkHTML($string,'p');
echo('Open Tags:'.$numberOfParagraphTags[0].' Close Tags:'.$numberOfParagraphTags[1]);

对于HTML块,尝试使用DomDocument PHP类而不是字符串。然后,您可以使用getElementsByTagName();等方法,这些方法将允许您更容易、更准确地计数标记。要将字符串加载到DomDocument中,可以这样做:

$doc = new DOMDocument();
$doc->loadHTML($string);

然后,按以下步骤计算标签数:

$tagList = $doc->getElementsByTagName($tag);
return $tagList.length;