Ankündigung

Einklappen
Keine Ankündigung bisher.

HTML5 Fragmente mit PHP prüfen

Einklappen

Neue Werbung 2019

Einklappen
X
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

  • HTML5 Fragmente mit PHP prüfen

    Im Rahmen von Unit-Tests möchte ich mit PHP die Resultate aus Methoden und Funktionen,
    welche mir HTML-Fragmente liefern, einen groben Valditätscheck unterziehen.

    Beispiel:
    PHP-Code:
    $html '<div id=test>56,40 €</div>';  //" " fehlen
    var_dump($test->validateHTML($html));  //bool(false); 
    Folgende Randbedingungen gelten für meine Anwendungen:
    • Muß im Browser laufen, da keine Konsole verfügbar ist
    • externe Services sind nicht nutzbar (Intranet)
    • Es dürfen keine speziellen Erweiterungen notwendig sein, die erst installiert werden müssen (z.B. tidy)
    • Megabyte große Frameworkkomponenten fallen auch aus, hab den Speicher auf vielen Zielsystemen nicht
    Aktuell versuche ich es über diesen Weg:
    Das HTML-Fragment wird mit DOMDocument geladen, gefiltert und wieder ausgegeben.
    Eine Filterung ist notwendig, da DOMDocument Probleme mit UTF-8 hat
    (s.a. zahlreiche User Contributed Notes zu DOMDocument::loadHTML).
    Das so erzeugte HTML wird mit dem gelieferten Fragment verglichen.

    Unschön sind die Workarounds wegen der UTF-8 Probleme.

    Gibt es Tipps zum obigen Vorgehen oder gar einen besseren Weg?

  • #2
    speziell zu deinem UTF8-Problem .. hast du den ERSTEN User-Kommentar gelesen ?

    der macht aus dem HTML nur ein XML .. und schon läuft auch UTF8 - jedenfalls steht das da

    interessanter sind die Anmerkungen in #6 - die Funktion wendet SGML Regeln an, kann also zu merkwürdigem markup führen...
    "Irren ist männlich", sprach der Igel und stieg von der Drahtbürste [IMG]http://www.php.de/core/images/smilies/icon_lol.gif[/IMG]

    Kommentar


    • #3
      Beim Fix aus dem ersten User-Kommentar wird aus einem
      HTML-Code:
      <div>4 €</div>
      ein
      HTML-Code:
      <div>4 &euro;</div>
      gemacht. Ebenso wenig gefällt mir diese Variante aus stackoverflow
      PHP-Code:
      $html '<div id="test">€</div>';
      $html mb_convert_encoding($html'HTML-ENTITIES'"UTF-8"); 
      läuft auf das Gleiche raus, nur kürzer.

      Bei Konstrukten wie in den Anmerkungen #6 versagt meine aktuelle Variante ebenso.
      Ziel ist es jedoch nicht, den W3C-Validator nachzubauen, sondern extrem grobe Fehler vorab anzuzeigen,
      die sich schnell mal bei Änderungen und Erweiterungen einschleichen.

      Kommentar


      • #4
        [man]tidy[/man]

        Kommentar


        • #5
          Ja, tidy wäre vermutlich schon die richtige Klasse für diesen Zweck.
          Doch leider ist es auf ca. 50% meiner Systeme tidy nicht verfügbar und kann auch nicht installiert werden.
          Zitat von jspit Beitrag anzeigen
          Es dürfen keine speziellen Erweiterungen notwendig sein, die erst installiert werden müssen (z.B. tidy)
          Der aktuelle Stand der Funktion:
          PHP-Code:
           /*
            * return false if $html is invalid
            */
            
          function validateHTML($html){
              
          $html preg_replace('/[^\x20-\x7E]|/u',''$html);
              
          $code '<!DOCTYPE html>'.$html;

              
          $doc = new DOMDocument();

              
          libxml_use_internal_errors(true);
              
          $loadError = !$doc->loadHTML($code); 
              
          $errors libxml_get_errors();
              
          libxml_use_internal_errors(false);
              if(
          $loadError or $errors) return false;

              
          $node $doc->getElementsByTagName("body")->item(0);
              
          $fragment $node->ownerDocument->saveHTML($node);

              return 
          preg_replace('~</?body>|[\x00-\x20]~','',$fragment) === str_replace(' ','',$html);
            } 

          Kommentar


          • #6
            Habe das jetzt nicht weiter ausgetestest, aber funktionert auf den ersten Blick ganz gut:
            Wahrscheinlich kannst du damit schon was anfangen.
            PHP-Code:
            $html '<div id=test>56,40 €</div>';  //" " fehlen
            var_dump(validateHTML($html));  //bool(false);  

            function validateHTML($html)
            {
                
            libxml_use_internal_errors(true);

                if (!
            $html simplexml_load_string($html)) {
                    
            $errors libxml_get_errors();
                    foreach (
            $errors as $error) {
                        break;  
                    }
                    
                    
            libxml_clear_errors();
                    return(
            $error->message);
                }
                return 
            TRUE;

            ergibt:
            Code:
             
             string 'AttValue: " or ' expected ' (length=26)

            Kommentar


            • #7
              sollte aber eigentlich noch mehr Fehler ergeben ... ich glaub auch nicht, dass das Abbrechen nach dem ersten Fehler (im Foreach) hilft - wäre schon besser, alle Fehler zu finden - aber durch XML werden da wohl wieder Fehler gefunden, die gar keine sind
              "Irren ist männlich", sprach der Igel und stieg von der Drahtbürste [IMG]http://www.php.de/core/images/smilies/icon_lol.gif[/IMG]

              Kommentar


              • #8
                sollte auch nur als Ansatz dienen. Natürlich ist die Fehlerroutine des XMLlib nicht auf HTML Attribute ausgelegt, so dass dann auch komische Ansätze wie href im Div nicht bemängelt werden.
                Aber nachdem das ja für Unit-Tests dienen soll, werden solche Fehler wohl eher seltener auftreten und dann ist da ja noch der Validator vom W3C dem man auch verwenden sollte wenn man etwas fürs Web erstellt.

                Kommentar


                • #9
                  An SimpleXML hatte ich auch schon gedacht und gleich wieder verworfen, da auch valides HTML wie
                  HTML-Code:
                  <input name="text" class="text" type="text" value="text eingeben" >
                  ​als Fehler ausgewiesen wird, wie eagle275 richtig bemerkt.
                  Das Strings wie
                  HTML-Code:
                  <unknown_tag>6</unknown_tag>
                  dabei als gültig ausgewiesen werden ist noch das kleinere Übel.
                  Der Codeschnipsel von protestix ist für mich dennoch nützlich, denn er brachte mich auf die Idee libxml_get_errors() auch für DOMDocument zu nutzen.
                  Werde das mal prüfen, ob das für mein Anliegen was bringt.

                  LG jspit

                  Edit: Hat Punkte gebracht. libxml_get_errors() liefert in einigen Fällen Fehler, wo loadHTML nicht false als Rückgabe liefert. Als schöner Nebeneffekt werden störende Warnungen jetzt unterdrückt. Der obige Code wurde aktualisiert.
                  Ein erster Browser-Unit-Test sieht ganz gut aus.

                  Kommentar


                  • #10
                    Hast du mal die hier versucht: https://ivopetkov.com/b/a-better-html5-parser-for-php/
                    Tutorials zum Thema Technik:
                    https://pilabor.com
                    https://www.fynder.de

                    Kommentar


                    • #11
                      ​Danke für den Link. Hab ich mir jetzt mal angesehen.
                      Zum Prüfen von HTML5-Fragmenten selbst hab ich nichts gefunden, was direkt nutzbar wäre.

                      Werden invalide Strukturen geladen, versucht die Klasse ohne zu meckern wie schon die Elternklasse DOMDocument die Struktur zu bereinigen.
                      Durch Laden und speichern wird z.B. aus diesen invaliden Bruchstück
                      HTML-Code:
                      <div id=test1>4 €
                      dies erzeugt:
                      HTML-Code:
                      <!DOCTYPE html><html><body><div id="test1">4 €</div></body></html>
                      Der Blick in den Quellcode der Klassen brachte einige neue Erkenntnisse, die zu Detailverbesserungen der obigen Funktion führten.

                      LG jspit





                      Kommentar


                      • #12
                        Willst du eigentlich auch auf richtige Verwendung und Schreibweise der Elemente und der erlaubten Attribute prüfen?



                        Kommentar


                        • #13
                          Nein, das überlasse ich Tools die das können, z.B. dem W3C Validation Service. Es geht mir darum, im Rahmen von Unit-Tests grobe Fehler vorab auszufiltern.
                          Unit-Tests für Klassen, die HTML-Fragmente erstellen, laufen auf einen exakten Stringvergleich zwischen einer fixen Vorlage und dem erzeugten HTML hinaus.
                          Ein schönes Beispiel dafür ist zu sehen, wenn man den Link vom Andreas folgt (github.com).
                          Soll nun im HTML-Fragment z.B. ein weiteres Attribut eingebaut werden, dann schlägt der Unittst erstmal fehl, bis alle fixen Vorlagen auf den aktuellen Stand gebracht wurden.
                          Zudem besteht die Gefahr, das in die Vorlagen selbst Fehler eingebaut werden oder es ist irgendwo an einer unwichtigen Stelle nur eine Space zuviel.
                          Der hohe Aufwand für die Anpassung der Tests steht oft in keinem Verhältnis zur Änderung/Erweiterung der Klasse selbst.

                          Wird für ein Unittest die obige Funktion benutzt, kann dieser ohne eine Änderung gestartet werden.

                          Ausblick:
                          Mit checkHTML() wird für eigene Unittests eine Methode zur Verfügung gestellt, welche die obige Funktion nutzt. Werden Formularelemente dynamisch erstellt, kann das erzeugte Element sogar mittels manueller Eingaben ausprobiert werden.

                          phpcheck_select.png
                          Funktionieren die Elemente wie gewünscht, kann für den "Feinschliff" der komplette Seitenquelltext des Test aus dem Browser genommen werden und per Validate by direct input mit dem W3C validiert werden.

                          Kommentar

                          Lädt...
                          X