web-dev-qa-db-ja.com

Simplexml_load_string()はエラーの解析に失敗します

Google Weather APIの応答(中国語の応答)をロード解析しようとしています。

ここ はAPI呼び出しです。

// This code fails with the following error
$xml = simplexml_load_file('http://www.google.com/ig/api?weather=11791&hl=zh-CN');

(!)警告:simplexml_load_string()[function.simplexml-load-string]:エンティティ:1行目:パーサーエラー:入力が適切なUTF-8ではありません。エンコードを示してください!バイト:0xB6 0xE0 0xD4 0xC6、11行目のC:\ htdocs\weather.php

この応答のロードが失敗するのはなぜですか?

simplexmlが正しくロードするように、応答をエンコード/デコードするにはどうすればよいですか?

編集:コードと出力は次のとおりです。

<?php
$googleData = file_get_contents('http://www.google.com/ig/api?weather=11102&hl=zh-CN');
$xml = simplexml_load_string($googleData);

(!)警告:simplexml_load_string()[function.simplexml-load-string]:エンティティ:1行目:パーサーエラー:入力が適切なUTF-8ではありません。エンコードを示してください!バイト:0xB6 0xE0 0xD4 0xC6 in C:\ htdocs\test4.php on line 3 Call Stack Time Memory Function Location 1 0.0020 314264 {main}()..\test4.php:0 2 0.1535 317520 simplexml_load_string(string(1364)) ..\test4.php:3

(!)警告:simplexml_load_string()[function.simplexml-load-string]:t_system data = "SI" />

(!)警告:simplexml_load_string()[function.simplexml-load-string]:^ 3行目のC:\ htdocs\test4.phpのコールスタック時間メモリ関数の場所10.0020 314264 {main}()..\test4。 php:0 2 0.1535 317520 simplexml_load_string(string(1364))..\test4.php:3

8
John Himmelman

ここでの問題は、SimpleXMLがHTTPヘッダーを調べてドキュメントで使用されている文字エンコードを判別せず、Googleのサーバーがそれを次のようにアドバタイズしている場合でもUTF-8であると単純に想定することです

Content-Type: text/xml; charset=GB2312

超秘密の魔法の変数$http_response_headerを使用してそのヘッダーを調べ、それに応じて応答を変換する関数を作成できます。そんな感じ:

function sxe($url)
{   
    $xml = file_get_contents($url);
    foreach ($http_response_header as $header)
    {   
        if (preg_match('#^Content-Type: text/xml; charset=(.*)#i', $header, $m))
        {   
            switch (strtolower($m[1]))
            {   
                case 'utf-8':
                    // do nothing
                    break;

                case 'iso-8859-1':
                    $xml = utf8_encode($xml);
                    break;

                default:
                    $xml = iconv($m[1], 'utf-8', $xml);
            }
            break;
        }
    }

    return simplexml_load_string($xml);
}
22
Josh Davis

更新:問題を再現できます。また、Firefoxは、生のXMLフィードを出力するときに、「簡体字中国語」として文字セットを自動スニッフィングします。 Googleフィードが誤ったデータ(UTF-8ではなく中国語の簡体字)を提供しているか、ブラウザーでフェッチされていないときに異なるデータを提供しています-Firefoxのcontent-typeヘッダーは明らかにutf-8

簡体字中国語(GB18030、これはFirefoxから提供されたもの)からの受信フィードをUTF-8に変換すると次のようになります。

 $incoming = file_get_contents('http://www.google.com/ig/api?weather=11791&hl=zh-CN');
 $xml = iconv("GB18030", "utf-8", $incoming);
 $xml = simplexml_load_string($xml);

ただし、根本的な問題についてはまだ説明も修正もされていません。私は今これを深く調べる時間がありません、多分他の誰かがそうします。私には、Googleが実際に間違ったデータを提供しているように見えます(これは私を驚かせるでしょう。彼らが私たちの人間のように間違いを犯したことを知りませんでした。:P)

5
Pekka

ちょうどこれに出くわした。これは機能しているようです(Webで見つけた関数自体、少し更新しただけです)。

header('Content-Type: text/html; charset=utf-8'); 


function getWeather() {

$requestAddress = "http://www.google.com/ig/api?weather=11791&hl=zh-CN";
// Downloads weather data based on location.
$xml_str = file_get_contents($requestAddress,0);
$xml_str = preg_replace("/(<\/?)(\w+):([^>]*>)/", "$1$2$3", $xml_str); 

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


// Parses XML
$xml = new SimplexmlElement($xml_str, TRUE);
// Loops XML
$count = 0;
echo '<div id="weather">';

foreach($xml->weather as $item) {

    foreach($item->forecast_conditions as $new) {

        echo "<div class=\"weatherIcon\">\n";
         echo "<img src='http://www.google.com/" .$new->icon['data'] . "'   alt='".$new->condition['data']."'/><br>\n";
        echo "<b>".$new->day_of_week['data']."</b><br>";
        echo "Low: ".$new->low['data']." &nbsp;High: ".$new->high['data']."<br>";
        echo "\n</div>\n";
        }

}

echo '</div>';
}


getWeather();
2
AR.

これは、Google WeatherAPIを解析するためにphpで作成したスクリプトです。

 <?php

function sxe($url)
{
$xml = file_get_contents($url);
foreach ($http_response_header as $header)
{
if (preg_match('#^Content-Type: text/xml; charset=(.*)#i', $header, $m))
{
switch (strtolower($m[1]))
{

case 'utf-8':
// do nothing
break;

case 'iso-8859-1':
$xml = utf8_encode($xml);
break;

default:
$xml = iconv($m[1], 'utf-8', $xml);
}
break;
}
}
return simplexml_load_string($xml);
}


$xml = simplexml_load_file('http://www.google.com/ig/api?weather=46360&h1=en-us');
$information = $xml->xpath("/xml_api_reply/weather/forecast_information");
$current = $xml->xpath("/xml_api_reply/weather/current_conditions");
$forecast = $xml->xpath("/xml_api_reply/weather/forecast_conditions");


print "<br><br><center><div style=\"border: 1px solid; background-color: #dddddd; background-image: url('http://mc-pdfd-live.dyndns.org/images/clouds.bmp'); width: 450\">";


print "<br><h3>";
print $information[0]->city['data'] . "&nbsp;" . $information[0]->unit_system['data'] . "&nbsp;" .     $information[0]->postal_code['data'];
print "</h3>";
print "<div style=\"border: 1px solid; width: 320px\">";
print "<table cellpadding=\"5px\"><tr><td><h4>";
print "Now";
print "<br><br>";
print "<img src=http://www.google.com" . $current[0]->icon['data'] . ">&nbsp;";
print "</h4></td><td><h4>";
print "<br><br>";
print "&nbsp;" . $current[0]->condition['data'] . "&nbsp;";
print "&nbsp;" . $current[0]->temp_f['data'] . "&nbsp;°F";
print "<br>";
print "&nbsp;" . $current[0]->wind_condition['data'];
print "<br>";
print "&nbsp;" . $current[0]->humidity['data'];
print "<h4></td></tr></table></div>";




print "<table cellpadding=\"5px\"><tr><td>";


print "<table cellpadding=\"5px\"><tr><td><h4>";
print "Today";
print "<br><br>";
print "<img src=http://www.google.com" . $forecast[0]->icon['data'] . ">&nbsp;";
print "</h4></td><td><h4>";
print "<br><br>";
print  $forecast[0]->condition['data'];
print "<br>";
print  "High&nbsp;" . $forecast[0]->high['data'] . "&nbsp;°F";
print "<br>";
print  "Low&nbsp;" . $forecast[0]->low['data'] . "&nbsp;°F";
print "</h4></td></tr></table>";

print "<table cellpadding=\"5px\"><tr><td><h4>";
print  $forecast[2]->day_of_week['data'];
print "<br><br>";
print "<img src=http://www.google.com" . $forecast[2]->icon['data'] . ">&nbsp;";
print "</h4></td><td><h4>";
print "<br><br>";
print  "&nbsp;" . $forecast[2]->condition['data'];
print "<br>";
print  "&nbsp;High&nbsp;" . $forecast[2]->high['data'] . "&nbsp;°F";
print "<br>";
print  "&nbsp;Low&nbsp;" . $forecast[2]->low['data'] . "&nbsp;°F";
print "</h4></td></tr></table>";


print "</td><td>";


print "<table cellpadding=\"5px\"><tr><td><h4>";
print  $forecast[1]->day_of_week['data'];
print "<br><br>";
print "<img src=http://www.google.com" . $forecast[1]->icon['data'] . ">&nbsp;";
print "</h4></td><td><h4>";
print "<br><br>";
print  "&nbsp;" . $forecast[1]->condition['data'];
print "<br>";
print  "&nbsp;High&nbsp;" . $forecast[1]->high['data'] . "&nbsp;°F";
print "<br>";
print  "&nbsp;Low&nbsp;" . $forecast[1]->low['data'] . "&nbsp;°F";
print "</h4></td></tr></table>";

print "<table cellpadding=\"5px\"><tr><td><h4>";
print  $forecast[3]->day_of_week['data'];
print "<br><br>";
print "<img src=http://www.google.com" . $forecast[3]->icon['data'] . ">&nbsp;";
print "</h4></td><td><h4>";
print "<br><br>";
print  "&nbsp;" . $forecast[3]->condition['data'];
print "<br>";
print  "&nbsp;High&nbsp;" . $forecast[3]->high['data'] . "&nbsp;°F";
print "<br>";
print  "&nbsp;Low&nbsp;" . $forecast[3]->low['data'] . "&nbsp;°F";
print "</h4></td></tr></table>";


print "</td></tr></table>";


print "</div></center>";


?>
2
cmluscco

URLクエリパラメータeo = utf-8を追加してみてください。この場合、答えはUTF-8エンコーディングのみになります。それは私を助けました。

http://www.google.com/ig/api?weather=?????&degree=??????&oe=utf-8&hl=es
1
Igor Vakulenko