SimpleXML和中文

时间:2011-06-08 21:57:17

标签: php xml encoding character-encoding simplexml

我正忙着尝试处理以下RSS提要:Yahoo Search RSS,一旦获取数据,使用以下代码:

$response = simplexml_load_string($data);

然而,当我询问简单的xml对象时,99%的汉字和字符串都消失了。

我尝试通过执行以下操作将传入数据转换为utf8:

$data = iconv("UTF-8", "UTF-8//TRANSLIT", $data);

但这也无济于事。

在数据点击simplexml_load_string之前100%罚款。但事后,它不是。

有什么想法吗?

3 个答案:

答案 0 :(得分:2)

您所描述的内容听起来像编码问题。编码就像一个链,如果它在处理的一个部分被破坏,数据就会被破坏。

当您从RSS服务器请求数据时,您将获得特定字符编码的数据。你应该找到的第一件事是对数据的编码。

Data URL: http://tw.blog.search.yahoo.com/rss?ei=UTF-8&p=%E6%95%B8%E4%BD%8D%E6%99%82%E4%BB%A3%20%E9%9B%9C%E8%AA%8C&pvid=QAEnPXeg.ioIuO7iSzUg9wQIc1LBPk3uWh8ABnsa

根据网站标题,编码为 UTF-8 。这是标准的XML编码。

但是,如果数据不是UTF-8编码而标题是这样说的,那么您需要找到正确的数据编码并在继续之前将其带入UTF-8。

接下来要检查的是simplexml_load_string()是否能够处理UTF-8数据。

我不使用simplexml,我使用DomDocument。所以我不能说是否。不过,我建议你改用DomDocument。它肯定支持UTF-8加载,它返回的所有数据也以UTF-8编码。你应该安全地假设simplexml也能正确处理UTF-8。

链条的下一部分是您的显示器。你写的是你的数据坏了。你怎么能这么说?你如何询问simplexml对象?


重新访问编码链

正如所写,编码就像一个链。如果一个元素断开,则整体结果会被破坏。要找出它断裂的地方,每个元素都必须自己检查。你想要的编码是UTF-8。

  • 输入数据:全部检查确定:
    • 检查:编码数据是否为UTF-8?结果:是的。从给定的数据URL获取的输入数据确实验证了UTF-8编码。可以使用提供的数据对此进行适当测试。
    • 检查:原始xml数据是否标记为UTF-8编码?结果:是的。这可以在第一个字节内验证:<?xml version="1.0" encoding="UTF-8" ?>
  • 简单XML数据
    • 检查:simple_xml是否支持UTF-8编码?结果:是的。
    • 检查:simple_xml是否返回UTF-8编码的值?结果:是和否。通常,simple_xml支持包含UTF-8编码文本的属性,但是带有xml数据的simple_xml对象实例的var_dump()表示它不支持CDATA。 CDATA用于相关数据。 CDATA元素将被删除。

此时,这看起来就像您所面临的错误。但是,您可以将所有CDATA元素转换为文本。为此,您需要在加载XML数据时指定一个选项。该选项是一个名为LIBXML_NOCDATA的常量,它将CDATA合并为文本节点。

以下是我用于上述测试的示例代码,演示了如何使用该选项:

$data_url = 'http://tw.blog.search.yahoo.com/rss?ei=UTF-8&p=%E6%95%B8%E4%BD%8D%E6%99%82%E4%BB%A3%20%E9%9B%9C%E8%AA%8C&pvid=QAEnPXeg.ioIuO7iSzUg9wQIc1LBPk3uWh8ABnsa';
$xml_data = file_get_contents($data_url);

$inspect = 256;
echo "First $inspect bytes out of ", count($xml_data),":\n", wordwrap(substr($xml_data, 0, $inspect)), "\n";
echo "UTF-8 test: ", var_dump(can_be_valid_utf8_statemachine($xml_data)), "\n";

$simple_xml = simplexml_load_string($xml_data, null, LIBXML_NOCDATA);
var_dump($simple_xml);


/**
 * Bitwise check a string if it would validate 
 * as utf-8.
 *
 * @param string $str
 * @return bool
 */
function can_be_valid_utf8_statemachine( $str ) { 
    $length = strlen($str); 
    for ($i=0; $i < $length; $i++) { 
        $c = ord($str[$i]); 
        if ($c < 0x80) $n = 0; # 0bbbbbbb 
        elseif (($c & 0xE0) == 0xC0) $n=1; # 110bbbbb 
        elseif (($c & 0xF0) == 0xE0) $n=2; # 1110bbbb 
        elseif (($c & 0xF8) == 0xF0) $n=3; # 11110bbb 
        elseif (($c & 0xFC) == 0xF8) $n=4; # 111110bb 
        else return false; # Does not match 
        for ($j=0; $j<$n; $j++) { # n bytes matching 10bbbbbb follow ? 
            if ((++$i == $length) || ((ord($str[$i]) & 0xC0) != 0x80)) 
                return false; 
        } 
    } 
    return true; 
}

我认为这会解决您的问题。如果不是DomDocument能够处理CDATA元素。由于编码链未经过进一步测试,您可能仍会在进一步处理数据时遇到编码问题,因此请注意保持编码直至输出。

答案 1 :(得分:1)

PHP的编码问题有很多原因。我查一下:

答案 2 :(得分:1)

我看了一眼: Simplexml_load_string() fail to parse error 做完后说的话(

 $data = file_get_contents('http://tw.blog.search.yahoo.com/rss?ei=UTF-8&p=%E6%95%B8%E4%BD%8D%E6%99%82%E4%BB%A3%20%E9%9B%9C%E8%AA%8C&pvid=QAEnPXeg.ioIuO7iSzUg9wQIc1LBPk3uWh8ABnsa');

$data = iconv("GB18030", "utf-8", $data);

$response = simplexml_load_string($data);

) 我可以看到中文字符,但是有一个解析错误。