3

libxmlエラーをキャッチする必要があります。しかし、私はこれに私のクラスを使用したいと思います。私は他の機能について知っていlibxml_get_errorsます。しかし、私は次のようなものが必要libxml_set_erroc_class("myclass")であり、すべての場合でエラーが発生するとクラスが呼び出されます。$dom->load(...)いずれの場合も、使用後にのような構造を作成したくありませんforeach(libxml_get_errors as $error) {....}。手伝って頂けますか?

4

3 に答える 3

10

libxml errorsxml自動検証が行われるため、ほとんどの場合、ドキュメントの読み取りまたは書き込み時に生成されます。

したがって、これは集中する必要がある場所であり、上書きする必要はありません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

これを直接行う機能はありません。オプションは次のとおりです。

  1. libxml を使用する PHP クラスを拡張し、独自のエラー処理ロジックをストック実装にラップする (あまり良くない)、または
  2. その PHP クラスのインスタンスを集約する独自のクラスを作成し、その周りに独自のパブリック インターフェイスを作成します (より良いのは、パブリック インターフェイスを制御でき、将来 PHP クラスが拡張された場合に問題が発生するリスクがないためです)。また
  3. 解析中にグローバルエラーハンドラーを置き換え、後で復元します(それほど強力ではなく、コードが他のコードを呼び出すと問題になる可能性がありますが、簡単に実行できます)

解決策 1 と 2 には、何があってもアプリケーション内の他のコードの動作を変更しないという利点があります。

于 2012-04-05T08:53:42.183 に答える
1

編集(例外とエラーを混同):

  1. set_exception_handlerを使用して、グローバルな例外をキャッチします。
  2. のような場合に、コードでこれらの例外をスローします$dom->load()libxmlそれ自体では例外をスローしないように見えるため、他のオプションは、その周りにラッパーを作成し、コードでラッパーを使用してlibxml、エラーをチェックし、必要な場合にそれらをスローすることです。
  3. 「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 に答える