月度归档:2013年07月

SimplePie 将中文编码成 HTML Entities 的解决方法

闲来折腾一个玩具五车书的过程中,需要用到解析RSS的地方,于是找到了强大的SimplePid。在使用的过程中遇到了一些问题,比如前段时间遇到的This XML document is invalid的问题,其实在这问题前还有一个问题,就是今天说的这个中文被编码的问题。

经过一番折腾之后,终于搞明白了怎么回事并找到了BT的解决方案。

SimplePie 在library/Sanitize.php文件的sanitize方法中使用DOMDocument对数据进行了一次加工,正式这次加工把中文编码成了HTML Entities。

那么为什么会这样呢?php.net上在关于DOMDocument::loadHTML说明下面已经有高人讨论到了此问题。

If you use loadHTML() to process utf HTML string (eg in Vietnamese), you may experience result in garbage text, while some files were OK. Even your HTML already have meta charset like

I have discovered that, to help loadHTML() process utf file correctly, the meta tag should come first, before any utf string appear. For example, this HTML file




Vietnamese - Tiếng Việt


will be OK with loadHTML() when tag appear tag.</p> <p>But the file below will not regcornize by loadHTML() because <title> tag contains utf string appear before <meta> tag.</p> <p><html><br /> <head><br /> <title> Vietnamese - Tiếng Việt




SimplePie其实已经通过的Santinize的preprocess方法加上了合理charset,按照上面的说明中文就不应该被编码了。看起来凶手另有其人啊,仔细看代码后发现,问题出现在SimplePie在saveHTML之前为了原样取回数据进行了一个处理,代码如下。

$real_body = $document->getElementsByTagName('body')->item(0)->childNodes->item(0);
$document->replaceChild($real_body, $document->firstChild);

这样处理的结果就像重新load一次HTML一样,但是因为这次每页charset设置,所以中文在这里被编码成了HTML Entities。

知道了原因就好办了,我是这样搞定她滴~。
如下修改library/Sanitize.php文件即可。

//修复开始
$unique_tag = '#'.uniqid().'#';
$data = $unique_tag.$data.$unique_tag;
//修复结束
$data = $this->preprocess($data, $type);
...
...
// Move everything from the body to the root
//注释掉下面紧邻的两行
//$real_body = $document->getElementsByTagName('body')->item(0)->childNodes->item(0);
//$document->replaceChild($real_body, $document->firstChild);

// Finally, convert to a HTML string
$data = trim($document->saveHTML());
//添加此行
list($_, $data, $_) = explode($unique_tag, $data);