在最近的一篇blog中,使用了colgroup HTML标签。没想到,使用了colgroup的帖子经过XHTML Validator的检查,发现居然不符合XHTML规范。究其原因,说是发现了如下错误:

Error Line 78 column 139: document type does not allow element "br" here.
...ALIGN: center"></col></colgroup><br />

但是奇怪的是,我的源代码中,</colgroup>后并没有<br />。我们可以用W3Shool给出的最简单的例子进行实验:

<table border="1">
  <colgroup span="3" style="color:#FF0000;"></colgroup>
  <tr>
    <td>1</td><td>2</td><td>3</td><td>4</td>
  </tr>
</table>

试着在Wordpress (2.0.x,包括最新的2.0.10。在2.2上则没有这个bug) 中编辑一个新帖子,在代码画面敲入上面这段代码,发布,再去看生成的HTML时就会发现变成了这个样子:

<table border="1">
  <colgroup span="3" style="color:#FF0000;"></colgroup><br />
  <tr>
    <td>1</td><td>2</td><td>3</td><td>4</td>
  </tr>
</table>

由于</colgroup>和<tr>之间是不允许有<br/>的,所以导致XHTML验证错误。

那么追根到底是在什么时候这个<br/>被添加到输出的HTML中的呢?调查了一下数据库,发现在数据库里面的内容还是没有<br/>的,这说明它是在读取post的内容时,由相关的Filter添加的。一个post的内容在被从数据库读出来,到被显示在网页上之间使用的是叫做the_content的Filter Tag。在Wordpress中,默认有如下Filter被添加到the_content的处理中:

add_filter('the_content', 'wptexturize');
add_filter(’the_content’, 'convert_smilies’);
add_filter(’the_content’, 'convert_chars’);
add_filter(’the_content’, 'wpautop’);

经过检查,发现位于/wp-includes/functions-formatting.php中的wpautop函数中有如下代码:

function wpautop($pee, $br = 1) {
 // …
 if ($br) $pee = preg_replace(‘|(?<!<br />)\s*\n|’, "<br />\n", $pee); // optionally make line breaks
 $pee = preg_replace(‘!(</?(?:table|thead|tfoot|caption|tbody|tr|td|th|div|dl|dd|dt|ul|ol|li|pre|select|form|blockquote|address|math|p|h[1-6])[^>]*>)\s*<br />!’, "$1", $pee);
 // …
 return $pee;
}

可见,该函数中用preg_replace函数通过正则表达式删除掉了添加在table,thead,tfoot等后面的<br />,却没有删除colgroup后面的<br/>。因此,只要在这一行添加colgroup即可修正这个bug。将修改后的functions-formatting.php重新上传到服务器后,在此进行XHTML验证,正常通过。