xml解析错误:'无效字符'

时间:2011-01-04 09:54:29

标签: php xml

我正在使用谷歌天气API来制作小部件。

除了今天我遇到了一个我无法解决的问题之外,一切都很好。 使用此位置呼叫时:

http://www.google.com/ig/api?weather=dunjkovec,medimurska,croatia&hl=en

我收到此错误:

XML parse error 9 'Invalid character' at line 1, column 169 (byte index 199)

我怀疑问题在于:Nedelišće

代码块就是这个:

$parser = xml_parser_create('UTF-8');
xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0);
xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1);
$ok = xml_parse_into_struct($parser, $data, $values);
if (!$ok) {
    $errmsg = sprintf("XML parse error %d '%s' at line %d, column %d (byte index %d)",
    xml_get_error_code($parser),
    xml_error_string(xml_get_error_code($parser)),
    xml_get_current_line_number($parser),
    xml_get_current_column_number($parser),
    xml_get_current_byte_index($parser));
}

$ data是xml的内容,$ values为空。

有人能帮助我吗?非常感谢你!

EDIT ----------------------------------

在阅读Hussein的帖子后,我发现问题在于文件的检索方式。

我尝试了file_get_contents和cURL。两者都返回:

这是产生问题的线。或者我想!我试过这个html_entity_decode($ data,ENT_NOQUOTES,'UTF-8')并且它无法正常工作,所以我做了一个发现,我无法回显xml的内容,我只能print_r它们并看到结果html源码!世界上任何其他位置都有效,只有这个产生问题...我想哭: - (

编辑2 --------------------------------

对于任何关心的人。我从api:

中检索xml文件后修复了这行代码
$data = mb_convert_encoding($data, 'UTF-8', mb_detect_encoding($data, 'UTF-8, ISO-8859-1', true));
$data = html_entity_decode($data,ENT_NOQUOTES,'UTF-8'); 

然后解析xml,它就像一个魅力。 我标记了侯赛因的回答,因为它让我走上正轨。

3 个答案:

答案 0 :(得分:4)

在阅读了你的问题之后,我在我的机器上尝试了同样的事情。 我做的是 1.从您发布的URL下载本地计算机上的xml文件。 2.使用xml解析脚本从XML准备结构。

令人惊讶的是,它在我的机器上运行得很好,即使XML有Nedelišće关键字。 所以,我看到了读取XML文件的问题。

如果您能告诉我您正在阅读xml格式google api的方式,那么调试会很容易。 你在使用CURL吗?

EDIT ---------------------------------------------- -

嗨0plus1,

我准备了一个辅助函数将这些特殊字符转换为html,使其能够解析..

我在这里粘贴整个代码。使用以下脚本..

function utf8tohtml($utf8, $encodeTags)
{
    $result = '';
    for ($i = 0; $i < strlen($utf8); $i++)
    {
        $char = $utf8[$i];
        $ascii = ord($char);
        if ($ascii < 128)
        {
            // one-byte character
            $result .= ($encodeTags) ? htmlentities($char , ENT_QUOTES, 'UTF-8') : $char;
        } else if ($ascii < 192)
        {
            // non-utf8 character or not a start byte
        } else if ($ascii < 224)
        {
            // two-byte character
            $result .= htmlentities(substr($utf8, $i, 2), ENT_QUOTES, 'UTF-8');
            $i++;
        } else if ($ascii < 240)
        {
            // three-byte character
            $ascii1 = ord($utf8[$i+1]);
            $ascii2 = ord($utf8[$i+2]);
            $unicode = (15 & $ascii) * 4096 +
                (63 & $ascii1) * 64 +
                (63 & $ascii2);
            $result .= "&#$unicode;";
            $i += 2;
        } else if ($ascii < 248)
        {
            // four-byte character
            $ascii1 = ord($utf8[$i+1]);
            $ascii2 = ord($utf8[$i+2]);
            $ascii3 = ord($utf8[$i+3]);
            $unicode = (15 & $ascii) * 262144 +
                (63 & $ascii1) * 4096 +
                (63 & $ascii2) * 64 +
                (63 & $ascii3);
            $result .= "&#$unicode;";
            $i += 3;
        }
    }
    return $result;
}


$curlHandle = curl_init();
$serviceUrl = "http://www.google.com/ig/api?weather=dunjkovec,medimurska,croatia&hl=en";
// setup the basic options for the curl
curl_setopt($curlHandle , CURLOPT_URL, $serviceUrl);
curl_setopt($curlHandle , CURLOPT_HEADER , 0);
curl_setopt($curlHandle , CURLOPT_HTTPHEADER , array("Cache-Control: no-cache","Content-type: application/x-www-form-urlencoded;charset=UTF-8"));
curl_setopt($curlHandle , CURLOPT_FOLLOWLOCATION , true);
curl_setopt($curlHandle , CURLOPT_RETURNTRANSFER , true);
curl_setopt($curlHandle , CURLOPT_USERAGENT, 'Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0)');
$data = curl_exec($curlHandle);
// echo $data;
$data = utf8tohtml($data , false);
echo $data;

$parser = xml_parser_create("UTF-8");
xml_parser_set_option($parser, XML_OPTION_TARGET_ENCODING, "UTF-8");
xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0);
xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1);
$ok = xml_parse_into_struct($parser, $data, $values);
if (!$ok) {
    $errmsg = sprintf("XML parse error %d '%s' at line %d, column %d (byte index %d)",
    xml_get_error_code($parser),
    xml_error_string(xml_get_error_code($parser)),
    xml_get_current_line_number($parser),
    xml_get_current_column_number($parser),
    xml_get_current_byte_index($parser));
}
echo "<pre>";
print_r($values);
echo "</pre>";

希望这会有所帮助。

谢谢!

侯赛因。

答案 1 :(得分:1)

响应中的Content-Type header field指定要使用ISO 8859-1编码的内容(请参阅response on Web-Sniffer.net)而不是UTF-8。因此,要么将ISO-8859-1指定为编码,要么省略该参数,xml_parser_create尝试识别编码。

答案 2 :(得分:0)

再次,您使用的是哪个php版本? xml_parser_create将编码作为参数,但仅用于输出,而不是某些版本的输入。 http://www.php.net/manual/en/function.xml-parser-create.php

您可能需要考虑创建一个空的utf-8字符串,然后使用从Google检索到的XML填充它,或者明确地将字符串转换为UTF-8。

string utf8_encode ( string $data )

Google正确地通知我们数据是UTF-8,但只在标题中,而不是在实际的XML中。