libxml error handler with OOP

error-handling, libxml2, oop, php

Solution

`libxml errors` are mostly generated when reading or writing `xml` document because automatic validation is done.

So this is where you should concentrate and you don't need to overwrite the `set_error_handler` .. Here is a prove of concept

Use Internal Errors

libxml_use_internal_errors ( true );

Sample XML

$xmlstr = <<< XML
<?xml version='1.0' standalone='yes'?>
<movies>
 <movie>
  <titles>PHP: Behind the Parser</title>
 </movie>
</movies>
XML;

echo "<pre>" ;

I guess this is an example of the kind of what you want to achieve

try {
    $loader = new XmlLoader ( $xmlstr );
} catch ( XmlException $e ) {
    echo $e->getMessage();
}

XMLLoader Class

class XmlLoader {
    private $xml;
    private $doc;
    function __construct($xmlstr) {
        $doc = simplexml_load_string ( $xmlstr );

        if (! $doc) {
            throw new XmlException ( libxml_get_errors () );
        }
    }
}

XmlException Class

class XmlException extends Exception {

    private $errorMessage = "";
    function __construct(Array $errors) {

        $x = 0;
        foreach ( $errors as $error ) {
            if ($error instanceof LibXMLError) {
                $this->parseError ( $error );
                $x ++;
            }
        }
        if ($x > 0) {
            parent::__construct ( $this->errorMessage );
        } else {
            parent::__construct ( "Unknown Error XmlException" );
        }
    }

    function parseError(LibXMLError $error) {
        switch ($error->level) {
            case LIBXML_ERR_WARNING :
                $this->errorMessage .= "Warning $error->code: ";
                break;
            case LIBXML_ERR_ERROR :
                $this->errorMessage .= "Error $error->code: ";
                break;
            case LIBXML_ERR_FATAL :
                $this->errorMessage .= "Fatal Error $error->code: ";
                break;
        }

        $this->errorMessage .= trim ( $error->message ) . "\n  Line: $error->line" . "\n  Column: $error->column";

        if ($error->file) {
            $this->errorMessage .= "\n  File: $error->file";
        }
    }

}

Sample Output

Fatal Error 76: Opening and ending tag mismatch: titles line 4 and title
  Line: 4
  Column: 46

I hope this helps

Thanks

Problem

I need catch libxml errors. But I want to use my class for this. I know about `libxml_get_errors` and other function. But I need something like `libxml_set_erroc_class("myclass")` and in all case for error will call my class. I don't want in each case after use `$dom->load(...)` create some construction like `foreach(libxml_get_errors as $error) {....}`. Can you help me?

Original source