【问题标题】:Failed to load external entity on simplexml_load_file at Openstreetmap无法在 Openstreetmap 的 simplexml_load_file 上加载外部实体
【发布时间】:2018-11-20 13:21:06
【问题描述】:

我最近查看了我们的一个网站,发现无法再搜索邮政编码。

我收到以下错误:

'加载外部实体失败'

如果我改为使用simplexml_load_string(),我会收到

'需要开始标签,'

这是我正在使用的代码:

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 标头有关,但我没有找到任何有用的信息。

【问题讨论】:

    标签: php xml openstreetmap nominatim


    【解决方案1】:

    在 OSM Nominatim 的使用政策中规定,您需要提供 User-AgentHTTP-Referer 请求标头来标识应用程序。因此,使用用户代理伪装成最终用户浏览器确实不是什么好礼节。

    您可以找到使用政策here。它还说 http 库使用的默认值(如 simplexml_load_file() 使用的那个)是不可接受的。

    您说您正在使用simplexml_load_string(),但没有说明您是如何将 XML 获取到该函数的。但最有可能的情况是,无论您使用哪种方法获取 XML 文件,您都忽略了传递强制标头。

    因此,我将使用php-curl 创建一个请求,提供这些标头之一来标识您的应用;并使用 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);
    }
    

    【讨论】:

      【解决方案2】:

      你可以使用curl添加自定义标题,我希望这段代码对你有用:

      <?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);
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-10-20
        • 2014-06-19
        • 2013-08-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多