无法在 Openstreetmap 的 simplexml_load_file 上加载外部实体
Failed to load external entity on simplexml_load_file at Openstreetmap
我最近查看了我们的一个网站,发现无法再搜索邮政编码。
我收到以下错误:
'Failed to load external entity'
如果我改用 simplexml_load_string()
我会收到
'Start tag expected, '<' not found'.
这是我正在使用的代码:
libxml_use_internal_errors(true);
$xml = simplexml_load_file('https://nominatim.openstreetmap.org/search?postalcode=28217&country=DE&format=xml&polygon=1&addressdetails=1&boundary=postalcode');
if (false === $xml) {
$errors = libxml_get_errors();
var_dump($errors);
}
我在某处读到它实际上可能与 HTTP 有关 headers 但我没有找到任何有用的信息。
您可以使用 curl
添加自定义 header,我希望这段代码对您有用:
<?php
$request_url='https://nominatim.openstreetmap.org/search?postalcode=28217&country=DE&format=xml&polygon=1&addressdetails=1&boundary=postalcode';
$ch = curl_init();
$timeout = 5;
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
'Accept-Language: en-US,en;q=0.9,fa;q=0.8,und;q=0.7',
'User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.79 Safari/537.36'));
curl_setopt($ch, CURLOPT_URL, $request_url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout);
$data = curl_exec($ch);
curl_close($ch);
echo($data);
在 OSM Nominatim 的使用政策中声明您需要提供 User-Agent
或 HTTP-Referer
请求 header 来识别应用程序。因此,使用 user-agent 伪装成 end-user 浏览器确实不是什么好礼仪。
您可以找到使用政策here。它还表示,http 库使用的默认值(如 simplexml_load_file()
使用的默认值)是不可接受的。
您说您正在使用 simplexml_load_string()
,但没有说明您如何获得该功能的 XML。但最有可能的情况是,无论您使用哪种方法获取 XML 文件,您也忽略了通过强制性 headers.
因此,我将使用 php-curl 创建一个请求,提供其中一个 header 来识别您的应用;并用 simplexml_parse_string()
.
解析结果 XML 字符串
例如:
// setup variables
$nominatim_url = 'https://nominatim.openstreetmap.org/search?postalcode=28217&country=DE&format=xml&polygon=1&addressdetails=1&boundary=postalcode';
$user_agent = 'ID_Identifying_Your_App v100';
$http_referer = 'http://www.urltoyourapplication.com';
$timeout = 10;
// curl initialization
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $nominatim_url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout);
// this is are the bits you are missing
// Setting curl's user-agent
curl_setopt($ch, CURLOPT_USERAGENT, $user_agent);
// you an also use this one (http-referer), it's up to you. Either one or both.
curl_setopt($ch, CURLOPT_REFERER, $http_referer);
// get the XML
$data = curl_exec($ch);
curl_close($ch);
// load it in simplexml
$xml = simplexml_load_string($data);
// This was your code, left as it was
if (false === $xml) {
$errors = libxml_get_errors();
var_dump($errors);
}
我最近查看了我们的一个网站,发现无法再搜索邮政编码。
我收到以下错误:
'Failed to load external entity'
如果我改用 simplexml_load_string()
我会收到
'Start tag expected, '<' not found'.
这是我正在使用的代码:
libxml_use_internal_errors(true);
$xml = simplexml_load_file('https://nominatim.openstreetmap.org/search?postalcode=28217&country=DE&format=xml&polygon=1&addressdetails=1&boundary=postalcode');
if (false === $xml) {
$errors = libxml_get_errors();
var_dump($errors);
}
我在某处读到它实际上可能与 HTTP 有关 headers 但我没有找到任何有用的信息。
您可以使用 curl
添加自定义 header,我希望这段代码对您有用:
<?php
$request_url='https://nominatim.openstreetmap.org/search?postalcode=28217&country=DE&format=xml&polygon=1&addressdetails=1&boundary=postalcode';
$ch = curl_init();
$timeout = 5;
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
'Accept-Language: en-US,en;q=0.9,fa;q=0.8,und;q=0.7',
'User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.79 Safari/537.36'));
curl_setopt($ch, CURLOPT_URL, $request_url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout);
$data = curl_exec($ch);
curl_close($ch);
echo($data);
在 OSM Nominatim 的使用政策中声明您需要提供 User-Agent
或 HTTP-Referer
请求 header 来识别应用程序。因此,使用 user-agent 伪装成 end-user 浏览器确实不是什么好礼仪。
您可以找到使用政策here。它还表示,http 库使用的默认值(如 simplexml_load_file()
使用的默认值)是不可接受的。
您说您正在使用 simplexml_load_string()
,但没有说明您如何获得该功能的 XML。但最有可能的情况是,无论您使用哪种方法获取 XML 文件,您也忽略了通过强制性 headers.
因此,我将使用 php-curl 创建一个请求,提供其中一个 header 来识别您的应用;并用 simplexml_parse_string()
.
例如:
// setup variables
$nominatim_url = 'https://nominatim.openstreetmap.org/search?postalcode=28217&country=DE&format=xml&polygon=1&addressdetails=1&boundary=postalcode';
$user_agent = 'ID_Identifying_Your_App v100';
$http_referer = 'http://www.urltoyourapplication.com';
$timeout = 10;
// curl initialization
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $nominatim_url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout);
// this is are the bits you are missing
// Setting curl's user-agent
curl_setopt($ch, CURLOPT_USERAGENT, $user_agent);
// you an also use this one (http-referer), it's up to you. Either one or both.
curl_setopt($ch, CURLOPT_REFERER, $http_referer);
// get the XML
$data = curl_exec($ch);
curl_close($ch);
// load it in simplexml
$xml = simplexml_load_string($data);
// This was your code, left as it was
if (false === $xml) {
$errors = libxml_get_errors();
var_dump($errors);
}