Мне нужно ловить ошибки libxml. Но я хочу использовать свой класс для этого. Я знаю о libxml_get_errors
и других функциях. Но мне нужно что-то вроде libxml_set_erroc_class("myclass")
и во всех случаях ошибка вызовет мой класс. Я не хочу в каждом случае после использования $dom->load(...)
создавать некоторую конструкцию, например foreach(libxml_get_errors as $error) {....}
. Вы можете мне помочь?
libxml errors
в основном генерируются при чтении или записи документа xml
поскольку выполняется автоматическая проверка.
Поэтому вам следует сконцентрироваться, и вам не нужно перезаписывать set_error_handler
. Вот доказательство концепции
Использовать внутренние ошибки
libxml_use_internal_errors ( true );
Пример XML
$xmlstr = <<< XML <?xml version='1.0' standalone='yes'?> <movies> <movie> <titles>PHP: Behind the Parser</title> </movie> </movies> XML; echo "<pre>" ;
Я думаю, это пример того, чего вы хотите достичь.
try { $loader = new XmlLoader ( $xmlstr ); } catch ( XmlException $e ) { echo $e->getMessage(); }
Класс XMLLoader
class XmlLoader { private $xml; private $doc; function __construct($xmlstr) { $doc = simplexml_load_string ( $xmlstr ); if (! $doc) { throw new XmlException ( libxml_get_errors () ); } } }
Класс XmlException
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"; } } }
Образец вывода
Fatal Error 76: Opening and ending tag mismatch: titles line 4 and title Line: 4 Column: 46
надеюсь, это поможет
благодаря
У нас нет возможности сделать это напрямую. Ваши варианты:
Решения 1 и 2 имеют то преимущество, что они не изменяют поведение какого-либо другого кода в приложении независимо от того, что.
редактировать (путать исключения с ошибками):
$dom->load()
. Поскольку libxml
, по-видимому, не libxml
исключений самостоятельно, другой вариант – создать вокруг него обертку, использовать оболочку в вашем коде и проверить ее на наличие ошибок libxml
и бросить их в необходимых случаях. Будьте осторожны, хотя set_exception_handler
все ваши исключения.
Вот пример того, что вы могли бы сделать:
//inheritance example (composition, though, would be better) class MyDOMWrapper extends DOMDocument{ public function load($filename, $options = 0){ $bool = parent::load($filename, $options); if (!$bool){ throw new MyDOMException('Shit happens. Feeling lucky.', 777); } } } class MyDOMException extends DOMException{ public $libxml; public function __construct($message, $code){ parent::__construct($message, $code); $this->libxml = libxml_get_errors(); } } class MyDOMExceptionHandler{ public static function handle($e){ //handle exception globally } } libxml_use_internal_errors(true); set_exception_handler(array('MyDOMErrorHandler', 'handle')); //global exception handler $myDom = new MyDOMWrapper(); $myDom->load('main.xml'); //when special handling is necessary try { $myDom = new MyDOMWrapper(); $myDom->load('main.xml'); } catch (MyDOMException $e) { //handle or throw $e; //rethrow }