xml error handling for 5.1

[email protected] (Rob Richards) Fri, 04 Feb 2005 07:43:00 -0500
Newsgroups php.xml.dev
Message-ID <[email protected]>
After trying many different approaches for better error handling 
support, I ultimately went with something simple - at least to start with.
At first, I thought about letting users set a dedicated error handler 
for the errors, but ran into issues with memory leaks.
Since they could exit or throw an exception in their handler, I couldnt 
find any way to be able to clean up stuff since the error would occur in 
the middle of libxml processing and never get a chance to return to the 
extension's internal function call.

 From here I decided to go the route of not issuing any errors from 
libxml directly and letting the user grab them after the function call 
returned.
This I have dumbed down quite alot to keep it simple and at least 
hopefully a starting point. It works as follows:

3 new functions in libxml extension as well as some constants:
constants which map to the error level:
LIBXML_ERR_NONE
LIBXML_ERR_WARNING
LIBXML_ERR_ERROR
LIBXML_ERR_FATAL

void libxml_use_interal_errors(boolean use_errors)
     - use interal error object. this will disable the php_error_docref 
errors when an error occurs within libxml.
    It will switch to libxml structured errors in order to populate the 
error structure, but will not automatically throw the errors.

object libxml_get_last_error()
    If a function fails (or the user just wants to check the last error 
state), a call to this will return a LibXMLError object.
    Went with the object as it was quick to implement

void libxml_clear_errors()
    - Clears the last libxml error so a subsequent call to 
libxml_get_last_error() (unless error) would return FALSE

Here's a few examples:
libxml_use_interal_errors(TRUE);
if ( ! ($t = DOMDocument::loadXML("<root>"))) {
$err = libxml_get_last_error();
var_dump($err);   
}

-- Output --
object(LibXMLError)#1 (5) {
  ["level"]=>  int(3)
  ["code"]=>  int(77)
  ["message"]=>  string(41) "Premature end of data in tag root line 1"
  ["file"]=>  string(0) ""
  ["line"]=>  int(1)
}

libxml_use_interal_errors(TRUE);
$xml = '<books><book>Book 1</booka></books>';
if (! ($xml = simplexml_load_string($xml))) {
    $err = libxml_get_last_error();
    var_dump($err);   
}

-- Output --
object(LibXMLError)#2 (5) {
  ["level"]=>  int(3)
  ["code"]=>  int(73)
  ["message"]=>  string(13) "expected '>'"
  ["file"]=>  string(0) ""
  ["line"]=>  int(1)
}

Not sure wether code is really needed or not as I'm not sure wether 
every libxml error code should be defined as a constant - there's quite 
a few of them. Also file is only populated if error from an xml file 
rather than a string.

Error handling stuff requires libxml 2.6.0+ and patch can be found at:
http://ctindustries.net/libxml/libxml_error.diff.txt

Any comments, suggestions or changes on this stuff? It's still in 
testing and I would like some feedback since I kind of winged this stuff 
- hard guessing how to implement from just the requests that the xml 
stuff needs better error support with no specifics - :)

Rob