我需要捕获 libxml 错误。但我想为此使用我的课程。我知道libxml_get_errors
和其他功能。但是我需要类似的东西,libxml_set_erroc_class("myclass")
并且在任何情况下都会出现错误会打电话给我的班级。我不希望在每种情况下使用后$dom->load(...)
创建一些结构,例如foreach(libxml_get_errors as $error) {....}
. 你能帮助我吗?
问问题
2865 次
3 回答
10
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
我希望这有帮助
谢谢
于 2012-04-05T09:25:34.563 回答
1
编辑(混淆异常与错误):
- 使用set_exception_handler捕获全局异常。
- 让您的代码在
$dom->load()
. 因为libxml
它本身似乎不会引发异常,所以您的另一个选择是围绕它创建一个包装器,在您的代码中使用包装器并让它检查libxml
错误并在必要的情况下抛出它们。 - 处理“myclass”中的异常。
请注意,这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
}
于 2012-04-05T08:50:10.500 回答
1
没有工具可以直接执行此操作。您的选择是:
- 扩展使用 libxml 的 PHP 类并将您的自定义错误处理逻辑包装在股票实现周围(不是那么好),或者
- 编写自己的类来聚合该 PHP 类的实例并围绕它创建自己的公共接口(更好,因为您可以控制公共接口,并且如果将来扩展 PHP 类,您不会冒问题的风险),或者
- 在解析期间替换全局错误处理程序并在之后恢复它(没有那么强大,如果您的代码调用其他代码可能会出现问题,但更容易做到)
解决方案 1 和 2 的优点是它们无论如何都不会修改应用程序中任何其他代码的行为。
于 2012-04-05T08:53:42.183 回答