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 в C:\htdocs\weather.php в строке 11
Почему загрузка этого ответа не удалась?
Как мне кодировать / декодировать ответ так, чтобы 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 в C:\htdocs\test4.php в строке 3 Время стека вызовов Функция памяти Расположение 1 0,0020 314264 {main}() ..\test4.php:0 2 0,1535 317520 simplexml_load_string (строка (1364)).. \ test4.php: 3
(!) Предупреждение: simplexml_load_string() [function.simplexml-load-string]: t_system data = "SI" />
(!) Предупреждение: simplexml_load_string() [function.simplexml-load-string]: ^ в C:\htdocs\test4.php в строке 3 Время памяти стека вызовов Расположение функции 1 0,0020 314264 {main} ().. \ test4. php: 0 2 0,1535 317520 simplexml_load_string ( string(1364)) ..\test4.php:3
5 ответов
Проблема здесь в том, что SimpleXML не смотрит на заголовок HTTP, чтобы определить кодировку символов, используемую в документе, и просто предполагает, что это UTF-8, даже если сервер Google действительно объявляет его как
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);
}
Обновление: я могу воспроизвести проблему. Кроме того, Firefox автоматически обнаруживает набор символов как "упрощенный китайский", когда я выводлю необработанный XML-канал. Либо канал Google обслуживает неверные данные (китайские упрощенные символы вместо символов UTF-8), либо он обслуживает другие данные, когда они не извлекаются в браузере - в заголовке типа контента в Firefox четко сказано 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)
Просто наткнулся на это. Кажется, это работает (сама функция, которую я нашел в сети, только что обновила):
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']." High: ".$new->high['data']."<br>";
echo "\n</div>\n";
}
}
echo '</div>';
}
getWeather();
Это скрипт, который я сделал в php для разбора Google Weather API.
<?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'] . " " . $information[0]->unit_system['data'] . " " . $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'] . "> ";
print "</h4></td><td><h4>";
print "<br><br>";
print " " . $current[0]->condition['data'] . " ";
print " " . $current[0]->temp_f['data'] . " °F";
print "<br>";
print " " . $current[0]->wind_condition['data'];
print "<br>";
print " " . $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'] . "> ";
print "</h4></td><td><h4>";
print "<br><br>";
print $forecast[0]->condition['data'];
print "<br>";
print "High " . $forecast[0]->high['data'] . " °F";
print "<br>";
print "Low " . $forecast[0]->low['data'] . " °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'] . "> ";
print "</h4></td><td><h4>";
print "<br><br>";
print " " . $forecast[2]->condition['data'];
print "<br>";
print " High " . $forecast[2]->high['data'] . " °F";
print "<br>";
print " Low " . $forecast[2]->low['data'] . " °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'] . "> ";
print "</h4></td><td><h4>";
print "<br><br>";
print " " . $forecast[1]->condition['data'];
print "<br>";
print " High " . $forecast[1]->high['data'] . " °F";
print "<br>";
print " Low " . $forecast[1]->low['data'] . " °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'] . "> ";
print "</h4></td><td><h4>";
print "<br><br>";
print " " . $forecast[3]->condition['data'];
print "<br>";
print " High " . $forecast[3]->high['data'] . " °F";
print "<br>";
print " Low " . $forecast[3]->low['data'] . " °F";
print "</h4></td></tr></table>";
print "</td></tr></table>";
print "</div></center>";
?>
Попробуйте добавить в URL-запрос параметр eo = utf-8. В этом случае ответом будет исключительно кодировка UTF-8. Это помогло мне.
http://www.google.com/ig/api?weather=?????°ree=??????&oe=utf-8&hl=es