28

I am using the following code:

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;
}

and getting these errors when the stream cannot connect:

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"

How can I handle these errors so I can display a user friendly message instead of what is shown above?

hakre
  • 193,403
  • 52
  • 435
  • 836
mrpatg
  • 10,001
  • 42
  • 110
  • 169

6 Answers6

49

I thinks this is a better way

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

more info: http://php.net/manual/en/function.libxml-use-internal-errors.php

hakre
  • 193,403
  • 52
  • 435
  • 836
Alex
  • 1,522
  • 1
  • 15
  • 17
28

I've found a nice example in the php documentation.

So the code is:

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;
    }
}

And the output, as we/I expected:

Failed loading 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
Community
  • 1
  • 1
BCsongor
  • 869
  • 7
  • 11
10

If you look at the manual, there is an options parameter:

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

Options list is available: http://www.php.net/manual/en/libxml.constants.php

This is the correct way to suppress warnings parsing warnings:

$xml = simplexml_load_file('file.xml', 'SimpleXMLElement', LIBXML_NOWARNING);
Mārtiņš Briedis
  • 17,396
  • 5
  • 54
  • 76
  • Didn't work for me, still generated an E_WARNING in PHP 5.4.x – Michael Butler Dec 29 '15 at 19:23
  • This answer is a simple solution that works, saved me headache! Note to those that may have errors: if you have more than one LIBXML_XXXX, be sure to seperate by pipe like LIBXML_NOCDATA | LIBXML_COMPACT | LIBXML_NOWARNING – Woody Apr 18 '19 at 16:58
7

This is an old question, but is still relevant today.

The correct way to handle exceptions when using the oop SimpleXMLElment is like so.

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.
}
Halfstop
  • 1,710
  • 17
  • 34
2

My little code:

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;
    }
}

Result example:

Caught exception: String could not be parsed as XML
Failed loading XML: 
- Opening and ending tag mismatch: Body line 3 and Bod-y
Robert G.
  • 317
  • 2
  • 8
-1

The documentation says that in the case of an error, simplexml_load_file returns FALSE. So, you can use the "shut-up" operator (@) in combination with a conditional statement:

if (@simplexml_load_file($file))
{
    // continue
}
else 
{
    echo 'Error!';
}
Ignas R
  • 3,314
  • 2
  • 23
  • 27
  • 19
    Not the shut-up not the shut up, please ! – mere-teresa Aug 20 '09 at 16:21
  • so something like this? 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 Aug 20 '09 at 16:23
  • 2
    You can do it without calling simplexml_load_file twice: $xml = @simplexml_load_file("..."); if ($xml) { ... } else { return 'Error'; } – Ignas R Aug 20 '09 at 16:26
  • 2
    mere-teresa, but he needs to suppress the warning here... Of course, you can also use the display_errors setting or convert errors to exceptions and then use try/catch, but this is much simpler... – Ignas R Aug 20 '09 at 16:28
  • @IgnasR you can do it even simpler: if (!$xml = simplexml_load_file($file)) { echo 'Error!'; return false; } else { //your code } – Adam B Jun 29 '13 at 21:50
  • Added comment to original question to recommend changing the selected answer, as this is a non-answer, and equates to "how to not-have-to handle errors on simplexml". The question was how to handle them - not how to avoid having to handle them. – Tim Ogilvy Apr 26 '17 at 03:26