PHP中的SimpleXML错误处理

28

我正在使用以下代码:

function GetTwitterAvatar($username){
$xml = simplexml_load_file("http://twitter.com/users/".$username.".xml");
$imgurl = $xml->profile_image_url;
return $imgurl;
}

function GetTwitterAPILimit($username, $password){
$xml = simplexml_load_file("http://$username:$password@twitter.com/account/rate_limit_status.xml");
$left = $xml->{"remaining-hits"};
$total = $xml->{"hourly-limit"};
return $left."/".$total;
}

当流无法连接时,会出现以下错误:

Warning: simplexml_load_file(http://twitter.com/users/****.xml) [function.simplexml-load-file]: failed to open stream: HTTP request failed! HTTP/1.0 503 Service Unavailable

Warning: simplexml_load_file() [function.simplexml-load-file]: I/O warning : failed to load external entity "http://twitter.com/users/****.xml" 

Warning: simplexml_load_file(http://...@twitter.com/account/rate_limit_status.xml) [function.simplexml-load-file]: failed to open stream: HTTP request failed! HTTP/1.0 503 Service Unavailable

Warning: simplexml_load_file() [function.simplexml-load-file]: I/O warning : failed to load external entity "http://***:***@twitter.com/account/rate_limit_status.xml"

我该如何处理这些错误,以便显示友好的用户提示信息,而不是上面显示的内容?


考虑更改所选答案?问题是“如何处理这些错误?”而所选答案仅告诉您如何避免出现这种情况。 - Tim Ogilvy
1
@TimOgilvy 已完成,谢谢。 - mrpatg
6个回答

49

我认为这是一种更好的方式

$use_errors = libxml_use_internal_errors(true);
$xml = simplexml_load_file($url);
if (false === $xml) {
  // throw new Exception("Cannot load xml source.\n");
}
libxml_clear_errors();
libxml_use_internal_errors($use_errors);

更多信息:http://php.net/manual/en/function.libxml-use-internal-errors.php


3
只有这个函数能回答这个问题。使用它与libxml_get_errors()libxml_get_last_error()一起可以获取错误信息。 - Markus Hedlund
1
然而,这并不能获取由simplexml_load_file转储的所有警告消息。 - Scott Chu
我尝试过这个,但是收到了一个警告信息,所以我只是使用了 $xml = @simplexml_load_file($url); ,没有警告并且按预期处理错误。 - bestprogrammerintheworld

28

我在php文档中找到了一个很好的例子。

所以代码是:

libxml_use_internal_errors(true);
$sxe = simplexml_load_string("<?xml version='1.0'><broken><xml></broken>");
if (false === $sxe) {
    echo "Failed loading XML\n";
    foreach(libxml_get_errors() as $error) {
        echo "\t", $error->message;
    }
}

输出结果和我们/我预期的一样:

加载XML失败

Blank needed here
parsing XML declaration: '?>' expected
Opening and ending tag mismatch: xml line 1 and broken
Premature end of data in tag broken line 1

2
然而,这并不能获取由simplexml_load_string转储的所有警告消息。 - Scott Chu

10

如果你查看手册,会发现有一个选项参数:

SimpleXMLElement simplexml_load_file ( string $filename [, string $class_name = "SimpleXMLElement" [, int $options = 0 [, string $ns = "" [, bool $is_prefix = false ]]]] )

可以查看选项列表:http://www.php.net/manual/en/libxml.constants.php

这是抑制解析警告的正确方法:

$xml = simplexml_load_file('file.xml', 'SimpleXMLElement', LIBXML_NOWARNING);

对我来说没有用,仍然在PHP 5.4.x中生成了E_WARNING。 - Michael Butler
这个答案是一个简单的解决方案,它有效地解决了我的问题,让我省去了很多麻烦!对于那些可能会出现错误的人,请注意:如果你有多个LIBXML_XXXX,请确保用管道符号分隔,如LIBXML_NOCDATA | LIBXML_COMPACT | LIBXML_NOWARNING。 - Woody

7

这是一个旧问题,但今天仍然相关。

使用oop SimpleXMLElment时处理异常的正确方法如下。

libxml_use_internal_errors(TRUE); // this turns off spitting errors on your screen
try {
  $xml = new SimpleXMLElement($xmlStringOfData);
} catch (Exception $e) {
  // Do something with the exception, or ignore it.
}

2

我的小代码:

try {
    libxml_use_internal_errors(TRUE);
    $xml = new SimpleXMLElement($xmlString);
    echo '<pre>'.htmlspecialchars($xml->asXML()).'</pre>';
} catch (Exception $e) {
    echo 'Caught exception: ' . $e->getMessage() . chr(10);
    echo 'Failed loading XML: ' . chr(10);
    foreach(libxml_get_errors() as $error) {
        echo '- ' . $error->message;
    }
}

结果示例:

Caught exception: String could not be parsed as XML
Failed loading XML: 
- Opening and ending tag mismatch: Body line 3 and Bod-y

-1
文档说明在出现错误的情况下,simplexml_load_file 函数会返回 FALSE。因此,您可以使用“shut-up”运算符(@)与条件语句结合使用:
if (@simplexml_load_file($file))
{
    // continue
}
else 
{
    echo 'Error!';
}

19
请不要沉默,不要保持沉默! - mere-teresa
function GetTwitterAvatar($username){ if(@simplexml_load_file("http://twitter.com/users/".$username.".xml")){ $xml = simplexml_load_file("http://twitter.com/users/".$username.".xml"); $imgurl = $xml->profile_image_url; return $imgurl; } else { return 'error'; } } - mrpatg
2
你可以不用两次调用simplexml_load_file来完成它:$xml = @simplexml_load_file("..."); 如果 ($xml) { ... } else { return '错误'; } - Ignas R
2
mere-teresa,但他需要在这里抑制警告...当然,您也可以使用display_errors设置或将错误转换为异常,然后使用try/catch,但这样更简单... - Ignas R
@IgnasR,你可以更简单地实现它:如果 (!$xml = simplexml_load_file($file)) { echo '错误!'; return false; } else { //你的代码 } - Adam B
在原问题中添加了评论,建议更改所选答案,因为这不是一个答案,等同于“如何在simplexml上不必处理错误”。问题是如何处理它们-而不是如何避免处理它们。 - Tim Ogilvy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接