TS: PHP-OOP: DOMDocument Parsing-Fehler einsammeln

Hallo,

wenn man mit DOMDocument ein Dokument einliest, kann man doch beimn Parsen die Fehler im DOM feststellen. Das ist sogar Standardeinstellung. Leider schlagen die dann durch.

Wie muss ich es richtig machen, damit ich die Fehler einsammeln kann, also im Script dann auch darauf zugreifen kann auf die Fehlermeldung?

$dom->validateOnParse = TRUE       ## kann man einschalten
$dom->strictErrorChecking = TRUE;  ## ist default, kann man ausschalten :-)

Ich möchte die Exceptions, die vermutlich von der Einstellung strictErrorChecking(?) abhängen, abfangen.

Wie muss ich das anfangen?

So funktioniert das jedenfalls nicht:

	try
	{
		$dom->loadHTML($page);
	}
	catch (Exception $__ex) 
	{
		$_errors[] = $__ex->getMessage();
	}	

Da schlägt immer noch die Warning durch:

Warning: DOMDocument::loadHTML(): Attribute alt redefined in Entity, line: 88 in F:\Xampp\html-parser\domdocument.class\get_linklist.php on line 13

Grüße
TS

  1. Hallo,

    Ich möchte die Exceptions, die vermutlich von der Einstellung strictErrorChecking(?) abhängen, abfangen.

    Es sind leider keine Exceptions. PHP ist und bleibt eben schmuddelig

    So funktioniert das jedenfalls nicht:

    	try
    	{
    		$dom->loadHTML($page);
    	}
    	catch (Exception $__ex) 
    	{
    		$_errors[] = $__ex->getMessage();
    	}	
    

    Da schlägt immer noch die Warning durch:

    Warning: DOMDocument::loadHTML(): Attribute alt redefined in Entity, line: 88 in F:\Xampp\html-parser\domdocument.class\get_linklist.php on line 13
    

    Ich habe jetzt zusätzlich den Error-Handler umgebogen:

    function handleError($errno, $errstr, $errfile, $errline, array $errcontext)
    {
      if (0 === error_reporting()) return false;
       throw new ErrorException($errstr, 0, $errno, $errfile, $errline);
    }
    

    und mittels Setting aktiviert:

    set_error_handler('handleError');
    

    Jetzt kann ich die erste Warning schon mal auffangen.
    Wo bleiben aber jetzt die weiteren? Wie kann ich die sammeln?

    Grüße
    TS

    1. Moin!

      Wo bleiben aber jetzt die weiteren? Wie kann ich die sammeln?

      Ich hoffe, Du findest die Lösung als Abfallprodukt dieser Überlegung und ergo in diesem Skript.

      Jörg Reinholz

  2. Tach!

    Wie muss ich es richtig machen, damit ich die Fehler einsammeln kann, also im Script dann auch darauf zugreifen kann auf die Fehlermeldung?

    Warning: DOMDocument::loadHTML(): Attribute alt redefined in Entity, line: 88 in F:\Xampp\html-parser\domdocument.class\get_linklist.php on line 13
    

    Das ist ja auch keine Exception sondern eine Warnung. Exceptions werden nur von ausgewählten Extensions geworfen, ansonsten gibts die herkömmlichen Fehlermeldungen.

    Man kann die Anzeige ausschalten (display_errors), man kann das Meldungs-Level heruntersetzen (error_reporting), man kann sie vorübergehend unterdrücken (@), man kann sich zusätzlich einen eigenen Errorhandler schreiben. Das Handbuch-Kapitel Error Handling and Logging weiß bestimmt auch noch was.

    dedlfix.

    1. Auch Tach :-)

      Wie muss ich es richtig machen, damit ich die Fehler einsammeln kann, also im Script dann auch darauf zugreifen kann auf die Fehlermeldung?

      Warning: DOMDocument::loadHTML(): Attribute alt redefined in Entity, line: 88 in F:\Xampp\html-parser\domdocument.class\get_linklist.php on line 13
      

      Das ist ja auch keine Exception sondern eine Warnung. Exceptions werden nur von ausgewählten Extensions geworfen, ansonsten gibts die herkömmlichen Fehlermeldungen.

      Das habe ich inzwischen begriffen. DOMDocument gaukelt zwar OOP vor, ist aber - wie so vieles in PHP - dabei nicht konsequent und benutzt klassisches Errorhandling.

      Ich habe das jetzt ungefähr so reingebastelt in mein Tool:

      Programm (nur Auszug!):

      <?php
      ## globales Sammelarray vereinbaren
      $_errors = array();
      
      #---------------------------------------------------------------------------
      function handleError($errno, $errstr, $errfile, $errline, array $errcontext) 
      {
          global $_errors;
      
          $_errors[] = array('errno' => $errno, 'errstr' => $errstr, 
      	'errfile' => $errfile, 'errline' => $errline); # , 'context' => $errcontext); 
      }
      #---------------------------------------------------------------------------
      
      # [...]
      set_error_handler('handleError');
      $dom->loadHTML($page);
      restore_error_handler();
      
      # [...]
      ?>
      <pre>
      <?php echo htmlspecialchars(print_r($_errors, 1)); ?>
      </pre>
      
      

      So lassen sich die Warnungen des Parsers sammeln.

      Leider landen dann auch alle anderen Fehler in diesem Array und müssen selber aussortiert und abgefangen werden. Schöner wäre es, wenn man nur die Warnings ausfiltern könnte.

      Außerdem stört mich die globale Variable $_errors für das Fehlersammelarray. Aber die bekomme ich wohl nicht weg, da die Signatur für den Errorhandler ja von PHP festgelegt ist und ich keinen weiteren Parameter (IN/OUT) mehr hinzufügen kann. Sehe ich das richtig?

      Ich bin also für jeden Verbesserungsvorschlag dankbar.

      Grüße
      TS

      1. Hallo,

        Das habe ich inzwischen begriffen. DOMDocument gaukelt zwar OOP vor, ist aber - wie so vieles in PHP - dabei nicht konsequent und benutzt klassisches Errorhandling.

        Also nicht PHP-OOP, sondern PH-POOP...

        Gruß
        Kalk

        1. Hallo Tabellenkalk,

          Also nicht PHP-OOP, sondern PH-POOP...

          ROTFL made my day 😂

          LG,
          CK

      2. Tach!

        Leider landen dann auch alle anderen Fehler in diesem Array und müssen selber aussortiert und abgefangen werden. Schöner wäre es, wenn man nur die Warnings ausfiltern könnte.

        Schau mal ins PHP-Handbuch! set_error_handler() hat einen zweiten Parameter. Außerdem ist der erste Parameter deines Callbacks das Level E_irgendwas. Damit kannst du fallweise entscheiden.

        Außerdem stört mich die globale Variable $_errors für das Fehlersammelarray. Aber die bekomme ich wohl nicht weg, da die Signatur für den Errorhandler ja von PHP festgelegt ist und ich keinen weiteren Parameter (IN/OUT) mehr hinzufügen kann. Sehe ich das richtig?

        Du kannst am Aufruf des Callbacks nichts ändern. Der kann aber auch eine Methode eines Objekts oder auch eine statische einer Klasse sein.

        dedlfix.

        1. Nochmal Re-Tach :-)

          Leider landen dann auch alle anderen Fehler in diesem Array und müssen selber aussortiert und abgefangen werden. Schöner wäre es, wenn man nur die Warnings ausfiltern könnte.

          Schau mal ins PHP-Handbuch! set_error_handler() hat einen zweiten Parameter. Außerdem ist der erste Parameter deines Callbacks das Level E_irgendwas. Damit kannst du fallweise entscheiden.

          Danke. Das Argument hatte ich übersehen. So kann ich das Umleiten der Fehlerbehandlung wenigstens auf E_WARNING beschränken.

          Außerdem stört mich die globale Variable $_errors für das Fehlersammelarray. Aber die bekomme ich wohl nicht weg, da die Signatur für den Errorhandler ja von PHP festgelegt ist und ich keinen weiteren Parameter (IN/OUT) mehr hinzufügen kann. Sehe ich das richtig?

          Du kannst am Aufruf des Callbacks nichts ändern. Der kann aber auch eine Methode eines Objekts oder auch eine statische einer Klasse sein.

          Da komme ich jetzt leider nicht mit. Nützt mir das dann was?

          Hieße das, dass ich ein "Fehlerobjekt" aus einer eigenen Klasse erzeugen müsste und dieses dann die Fehlermeldungen (gekapselt) sammeln kann, sofern es eine Methode mit passender Signatur hat?

          Und über seine übrigen Methoden könnte ich die Fehler dann abhandeln/bearbeiten lassen.

          Lass ich mir mal durch den Kopf gehen.

          Grüße TS

          1. Tach!

            Außerdem stört mich die globale Variable $_errors für das Fehlersammelarray.

            Du kannst am Aufruf des Callbacks nichts ändern. Der kann aber auch eine Methode eines Objekts oder auch eine statische einer Klasse sein.

            Da komme ich jetzt leider nicht mit. Nützt mir das dann was?

            Hieße das, dass ich ein "Fehlerobjekt" aus einer eigenen Klasse erzeugen müsste und dieses dann die Fehlermeldungen (gekapselt) sammeln kann, sofern es eine Methode mit passender Signatur hat?

            Genau das. Die Methode muss natürlich noch an set_error_handler() übergeben werden und nicht einfach nur so da sein ;) Aber sonst, ja, hast du eine schöne Klasse, in der du alles kapseln kannst, ohne dass du mit global auf irgendwas Auswärtiges zugreifen musst und Methoden hinzufügen kannst, ohne abseits einzelnstehende Funktionen hinlegen zu müssen.

            dedlfix.

  3. Moin!

    … F:\Xampp\html-parser\domdocument.class\get_linklist.php on line 13
    

    Xampp. Warum tust Du Dir das eigentlich an? Ich würde zu einem Linux-Server in einer VM greifen. Entweder VMWare-Player oder Virtual Box. Wenn man überhaupt gezwungen ist, unter Windows zu arbeiten... (siehe Parlakom-Katastrophe)

    Jörg Reinholz

    1. Selber Moin :-)

      … F:\Xampp\html-parser\domdocument.class\get_linklist.php on line 13
      

      Xampp. Warum tust Du Dir das eigentlich an? Ich würde zu einem Linux-Server in einer VM greifen. Entweder VMWare-Player oder Virtual Box. Wenn man überhaupt gezwungen ist, unter Windows zu arbeiten... (siehe Parlakom-Katastrophe)

      Kurze Antwort:

      Weil die Schüler der AG auch alle einen XAMPP zur Verfügung haben und ich zumindest ausprobieren muss, ob die Beispiele klappen, die ich ihnen auf ihre Fragen liefere.

      Lange Antwort:

      passt hier nicht rein ;-P

      1. Moin!

        Kurze Antwort:

        Weil die Schüler der AG auch alle einen XAMPP zur Verfügung haben und ich zumindest ausprobieren muss, ob die Beispiele klappen, die ich ihnen auf ihre Fragen liefere.

        Klingt wie ein Argument.

        Lange Antwort:

        passt hier nicht rein ;-P

        Ah. Du meinst das "an die Decke gehen", weil die Arbeitsgemeinschaft Rechner mit Windows (XP?) hat :)

        Jörg Reinholz

        1. Re-Moin!

          Lange Antwort:

          passt hier nicht rein ;-P

          Ah. Du meinst das "an die Decke gehen", weil die Arbeitsgemeinschaft Rechner mit Windows (XP?) hat :)

          So ungefähr.
          In der Schule haben wir einen zentralen Webserver auf einem Linux-Host. Darauf hat jeder Teilnehmer einen Account und eine eigene Domain. So kann man dafür sorgen, dass alle mit den gleichen Rahmenbedingungen arbeiten.

          Aber wir haben keine PCs mehr für die AG. Da bringen die Teilnehmer (Schüler, wie Lehrer) ihre Lappis mit, auf denen sie dann i.d.R. auch zuhause ihre Übungen machen. Und die arbeiten dann möglichst mit der gleichen XAMPP-Version - möglichst.

          Grüße
          TS