REGEX nicht geschlossene <li>

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

  • REGEX nicht geschlossene <li>

    Hallo in die Runde,

    nach langem brauch ich nun doch eure Hilfe bei einem Regex.

    Ich möchte in einem HTML-Template unsauberes HTML bereinigen.
    Natürlich hab ich mich vorab in Google und vielen Foren informiert und anscheinend sei TIDY oder beautiful soup hierfür das beste.

    Leider kann ich diese nicht auf dem Webserver installieren da Managed.

    Gefunden habe ich dann zumindst eine PHP Klasse ==> HTML fixer | Barattalo

    Oder online welches auch mit Regex arbeitet ==> HTML FIXER - FIXER (echt super)

    dieser funktioniert schon ganz gut allerdings schwächelt er bei nicht geschlossenen <li> Tags diese schließt er immer ganz am Ende beim </ul>

    Deswegen wollte ich das nun selbst mit einem preg_match/preg_replace angehen.

    Hier ein Beispiel HTML bei dem die offenen <li> geschlossen werden sollen:
    Code:
    <UL>
    <LI><STRONG>1 Gewicht:&nbsp;295 g</STRONG> </li>
    <LI><STRONG>2 Obermaterial aus Airmesh</STRONG>verbessert
    <LI><STRONG>3 dsfsdfds dsfsdfsd</STRONG> 
    <LI><STRONG>4 Obermaterial aus Airmesh</STRONG>verbessert
    </ul>
    Hier mein Regex Versuch:
    Der RegExp-Evaluator - RegExp-Evaluator - Ergebnis

    Erklärung:
    (<li>)(.+?)(?!</li>)(<li>)

    ==> (?!</li>) ist ein versuch mit Assertions das diese Zeichenkette nicht drin vorkommen kann

    Bisher gibt er mir komischerweise immer Aufzählung 1,3 zurück.
    Vielleicht könnt ihr mir hier helfen.

    Perfekt wäre natürlich dann mit preg_replace ==> $1 $2 </li>$4
    die offenen tags automatische schließen zu lassen, wobei ich wahrscheinlich hier dann mit preg_match_all und einer schleife arbeiten muss oder?

    Beste Grüße
    RegEx Noob
    Zuletzt geändert von tomtherock; 19.04.2013, 12:10.

  • #2
    Das habe ich bis heute auch noch nicht begriffen. Wenn ich schreibe, Ausdruck muss vorausgehen, dann wird das richtige Ergebnis geliefert. Nur die Umkehrung versagte bisher.

    PHP-Code:
    $pattern '~(<li>)(.+?)(?<=</li>)(\r|\n)~is'

    /*
        [0] => Array
            (
                [0] => <LI><STRONG>1 Gewicht:&nbsp;295 g</STRONG> </li>
            )

        [1] => Array
            (
                [0] => <LI>
            )

        [2] => Array
            (
                [0] => <STRONG>1 Gewicht:&nbsp;295 g</STRONG> </li>
            )

        [3] => Array
            (
                [0] => 
            )
    */ 

    Kommentar


    • #3
      mhhh muss doch ne Lösung geben, hab sonst wo leider nichts gefunden und selbst bekomme ich das leider nicht hin, da bin ich mit den RegEx echt überfordert...einfache Sachen gehen .

      Kommentar


      • #4
        Es wird daran liegen, dass in 2, also in (.+?) die Zeichenfolge </li> bereits mit durchrutscht und (?<!</li>) nicht mehr greifen kann. Wenn man jetzt aber statt(.+?) eine Zeichenklasse wie ([^<>]+?)verwenden würde, so würde <STRONG> schon mit einbegriffen.

        PHP-Code:
        $pattern '~(<li>)(.+?)(?<!</li>)(\r\n)(<li>)~is'

        /*

            [1] => Array
                (
                    [0] => <LI>
                )

            [2] => Array
                (
                    [0] => <STRONG>1 Gewicht:&nbsp;295 g</STRONG> </li>
                           <LI><STRONG>2 Obermaterial aus Airmesh</STRONG>verbessert
                )

        */ 

        Kommentar


        • #5
          mhhh ja stimmt, oder einfach doch mit in Kombination mit preg_split/explode arbeiten. Liefert bisher noch das beste Ergebnis. Evtl. vorher noch die <ul> auf endtag prüfen und dann jedes <ul> mit explode('<li>') prüfen oder besser preg_split() falls style definitionen im <li> vorkommen.

          Und danach <li> für <li> prüfen und anpassen.

          PHP-Code:

          preg_split
          ('~<li>~is')

          Array
          (
              [
          0] => <UL>
              [
          1] => STRONG>1 Gewicht:&nbsp;295 g</STRONG>
              [
          2] => hfskdhfsd </li>
              [
          3] => STRONG>2 Obermaterial aus Airmesh</STRONG>verbessert
              
          [4] => STRONG>3 dsfsdfds dsfsdfsd</STRONG
              [
          5] => STRONG>4 Obermaterial aus Airmesh</STRONG>verbessert
          </ul>

          Kommentar


          • #6
            Das wird wohl einfacher sein. Eine weitere Möglichkeit wären zwei Durchläufe. Im ersten Durchlauf überall vor <li> ein </li> einfügen (außer bei <ul> und <li>) und im zweiten Durchlauf nur doppelte </li> wieder entfernen bzw. gegen ein einfaches </li> auszutauschen.
            Zuletzt geändert von Melewo; 19.04.2013, 16:41.

            Kommentar


            • #7
              Leider kann ich diese nicht auf dem Webserver installieren da Managed
              Und wenn du an den Support schreibst, dass sie dir das Tidy-Modul nachinstallieren?

              Kommentar


              • #8
                ja ist jetzt keine super brisante Sache zudem such ich immer vorwiegend Lösung welche ich für alle meine Projekte einsetzen kann ohne extra Module für PHP.

                Aber denke die Klasse die ich gefunden hab in Verbindung mit der Sonderbehandlung der <li> sollte reichen.

                Vielen Dank nochmal
                wenn ich eine Funktion fertig hab die gut funktioniert poste ich Sie hier natürlich

                Kommentar


                • #9
                  Valide bekommst Du das auch so, zwar nicht in zwei, wie ich zuerst dachte, doch in drei Schritten. Mit den Steuerzeichen musst Du mal sehen, \n oder \r oder \r\n, doch irgendetwas davon sollten wohl eigentlich alle Systeme kennen, denke ich mir. Muss halt noch eine Bedingung erfüllt werden, dass nur zwischen <ul> und </ul> eine Änderung erfolgt, doch das sollte ja auch noch hinzubekommen sein.

                  PHP-Code:
                  $subject '<UL>
                  <LI><STRONG>1 Gewicht:&nbsp;295 g</STRONG> </LI>
                  <LI><STRONG>2 Obermaterial aus Airmesh</STRONG>verbessert
                  <LI><STRONG>3 dsfsdfds dsfsdfsd</STRONG> 
                  <LI><STRONG>4 Obermaterial aus Airmesh</STRONG>verbessert
                  </ul>'
                  ;


                  $subject preg_replace("~\r\n~""</li>\r\n"$subject);
                  $subject preg_replace("~<ul></li>~i""<ul>"$subject);
                  $subject preg_replace("~</li></li>~i""</li>"$subject);

                  echo 
                  "Valide:\n\n".$subject."\n\n";

                  /* Ausgabe (Quelltextansicht)

                  Valide:

                  <ul>
                  <LI><STRONG>1 Gewicht:&nbsp;295 g</STRONG> </li>
                  <LI><STRONG>2 Obermaterial aus Airmesh</STRONG>verbessert</li>
                  <LI><STRONG>3 dsfsdfds dsfsdfsd</STRONG> </li>
                  <LI><STRONG>4 Obermaterial aus Airmesh</STRONG>verbessert</li>
                  </ul>

                  */ 
                  Noch einen weiteren Schritt, um den Quelltext einheitlicher zu gestalten:

                  PHP-Code:
                  $subject preg_replace_callback("(<(.+?)>)",

                      function (
                  $inhalt) {
                      return 
                  "<".strtolower($inhalt[1]).">";
                      },
                      
                  $subject
                  );

                  echo 
                  "Einheitlicher:\n\n".$subject."\n\n";

                  /* Ausgabe (Quelltextansicht)

                  Einheitlicher:

                  <ul>
                  <li><strong>1 Gewicht:&nbsp;295 g</strong> </li>
                  <li><strong>2 Obermaterial aus Airmesh</strong>verbessert</li>
                  <li><strong>3 dsfsdfds dsfsdfsd</strong> </li>
                  <li><strong>4 Obermaterial aus Airmesh</strong>verbessert</li>
                  </ul>

                  */ 
                  Zuletzt geändert von Melewo; 19.04.2013, 19:42.

                  Kommentar


                  • #10
                    Ein zusammenhängendes Beispiel, sollte eigentlich seine Aufgaben erfüllen.

                    PHP-Code:
                    <?php error_reporting(E_ALL);
                      
                    $doc '<!DOCTYPE html>
                    <html>

                    <head>
                    <title>Test</title>
                    </head>

                    <body>
                    <h1>Test mit Liste</h1>
                    <UL>
                    <LI><STRONG>1 Gewicht:&nbsp;295 g</STRONG> </LI>
                    <LI><STRONG>2 Obermaterial aus Airmesh</STRONG>verbessert
                    <LI><STRONG>3 dsfsdfds dsfsdfsd</STRONG> 
                    <LI><STRONG>4 Obermaterial aus Airmesh</STRONG>verbessert
                    </ul>

                    </body>
                    </html>'
                    ;

                    preg_match_all("~<ul>([\S\s]+?)</ul>~i"$doc$listen);

                    $subject $listen[0][0]; 

                    $subject preg_replace("~(\r\n|\r|\n)~""</li>$1"$subject);
                    $subject preg_replace("~<ul></li>~i""<ul>"$subject);
                    $subject preg_replace("~</li></li>~i""</li>"$subject);

                    $subject preg_replace_callback("(<(.+?)>)",

                        function (
                    $inhalt) {
                        return 
                    "<".strtolower($inhalt[1]).">";
                        },
                        
                    $subject
                    );

                    echo 
                    "Fertig:\n\n".$subject."\n\n";

                    /* Ausgabe (Quelltextansicht)

                    Fertig:

                    <ul>
                    <li><strong>1 Gewicht:&nbsp;295 g</strong> </li>
                    <li><strong>2 Obermaterial aus Airmesh</strong>verbessert</li>
                    <li><strong>3 dsfsdfds dsfsdfsd</strong> </li>
                    <li><strong>4 Obermaterial aus Airmesh</strong>verbessert</li>
                    </ul>

                    */
                    ?>

                    Kommentar


                    • #11
                      PHP-Code:
                      <?php
                      error_reporting
                      (-1);
                      ini_set('display_errors'TRUE);

                      $doc '<!DOCTYPE html>
                      <html>

                      <head>
                      <title>Test</title>
                      </head>

                      <body>
                      <h1>Test mit Liste</h1>
                      <UL>
                      <LI><STRONG>1 Gewicht:&nbsp;295 g</STRONG> </LI>
                      <LI><STRONG>2 Obermaterial aus Airmesh</STRONG>verbessert
                      <LI><STRONG>3 dsfsdfds dsfsdfsd</STRONG> 
                      <LI><STRONG>4 Obermaterial aus Airmesh</STRONG>verbessert
                      </ul>

                      </body>
                      </html>'
                      ;

                      $dom = new DOMDocument;
                      $dom->loadHTML($doc);
                      echo 
                      $dom->saveHTML();
                      Zuletzt geändert von combie; 19.04.2013, 22:03.
                      Wir werden alle sterben

                      Kommentar


                      • #12
                        Ganz so einfach scheint das aber wohl mit DOM auch nicht zu sein. Damit erhalte ich zwar eine valide Liste, jedoch der Inhalt der Liste wird verstümmelt ausgegeben, da die Strong-Tags aus Value entfernt werden.

                        PHP-Code:
                        $dom = new DOMDocument;
                        $dom->loadHTML($doc);
                        $liste $dom->getElementsByTagName("li");

                        echo 
                        "<ul>\n";

                        foreach (
                        $liste as $list) {

                            echo 
                        "<li>".$list->nodeValue."</li>\n";
                        }
                        echo 
                        "</ul>\n";

                        /* Ausgabe (Quelltextansicht):

                        <ul>
                        <li>1 Gewicht: 295 g </li>
                        <li>2 Obermaterial aus Airmeshverbessert
                        </li>
                        <li>3 dsfsdfds dsfsdfsd 
                        </li>
                        <li>4 Obermaterial aus Airmeshverbessert
                        </li>
                        </ul>

                        */ 
                        Edit: Was mir noch eingefallen ist, meine bisherige Variante wird versagen bzw. fehlerhafte Ergebnisse liefern, wenn sich ein Listenpunkt (Listenelement) über mehrere Zeilen erstreckt.

                        Zitat von tomtherock Beitrag anzeigen
                        dieser funktioniert schon ganz gut allerdings schwächelt er bei nicht geschlossenen <li> Tags diese schließt er immer ganz am Ende beim </ul>
                        Wird wohl einen guten Grund haben. Deine Listen scheinen nicht wirklich invalide zu sein.

                        Es ist zwar nach HTML-Standard erlaubt, das abschließende </li>-Tag wegzulassen, doch davon ist abzuraten.
                        SELFHTML: HTML/XHTML / Elemente zur Textstrukturierung / Listen

                        Nehmen Sie bitte zur Kenntnis das die Tags “li” und “p” nicht beendet wurden. In HTML (nicht in XHTML) ist es erlaubt auf die Tags </li> and </p> zu verzichten..so wie hier geschehen.
                        HTML + CSS - ein Einstieg
                        Zuletzt geändert von Melewo; 20.04.2013, 06:22.

                        Kommentar


                        • #13
                          Was machst du da?
                          Und warum?

                          Das von mir gepostete Beispiel erzeugt:
                          HTML-Code:
                          <!DOCTYPE html>
                          <html><head><title>Test</title></head><body>
                          <h1>Test mit Liste</h1>
                          <ul><li><strong>1 Gewicht:&nbsp;295 g</strong> </li>
                          <li><strong>2 Obermaterial aus Airmesh</strong>verbessert
                          </li><li><strong>3 dsfsdfds dsfsdfsd</strong> 
                          </li><li><strong>4 Obermaterial aus Airmesh</strong>verbessert
                          </li></ul></body></html>
                          Und da sind alle Strong Dinger drin.
                          Die werden also nicht entfernt.


                          Du hast das schöne DOM und klöppelst das HTML trotzdem selber....
                          Warum nur?
                          Zuletzt geändert von combie; 20.04.2013, 06:25.
                          Wir werden alle sterben

                          Kommentar


                          • #14
                            Zitat von combie Beitrag anzeigen
                            Was machst du da?
                            Und warum?
                            Gute Frage, Du hast recht, ich hatte gestern das </li> am Zeilenanfang übersehen, da ich nur auf das Zeilenende geachtet hatte. Da war ich reichlich blind, so wäre es natürlich wesentlich einfacher.

                            Edit: Auch wenn es mit DOM wesentlich einfacher geht, doch nun greifen die Ersetzungen auch wenn sich ein Listeneintrag über mehrere Zeilen erstreckt und liefern eine formatierte Ausgabe. Zumindest funktioniert es erst einmal bei einer Liste auf einer Seite. Wenn sich mehrere Listen auf einer Seite befinden sollten, so müsste noch einiges erweitert und umgebaut werden.

                            PHP-Code:
                            <?php error_reporting(E_ALL);
                              
                            $doc '<!DOCTYPE html>
                            <html>

                            <head>
                            <title>Test</title>
                            </head>

                            <body>
                            <h1>Test mit Liste</h1>
                            <UL>
                            <LI><STRONG>1 Gewicht: 295 g</STRONG> </LI>
                            <LI><STRONG>2 Obermaterial aus Airmesh</STRONG> verbessert
                            und der Listeneintrag erstreckt sich über mehrere Zeilen
                            und noch eine Zeile mehr oder so.
                            <LI><STRONG>3 dsfsdfds dsfsdfsd</STRONG> 
                            <LI><STRONG>4 Obermaterial aus Airmesh</STRONG> verbessert
                            </ul>
                            <p>Schlusszeile</p>
                            </body>
                            </html>'
                            ;

                            preg_match("~(?P<beginn><!DOCTYPE.*?[\S\s]+?)(?P<liste><ul>[\S\s]+?</ul>)(?P<ende>[\S\s]+?</html>)~i"$doc$listen);

                            $subject $listen["liste"]; 

                            $subject preg_replace("~(\r\n|\r|\n)<li>~i""</li>$1<li>"$subject);
                            $subject preg_replace("~<ul></li>~i""<ul>"$subject);
                            $subject preg_replace("~(?<!</li>)(\r\n|\r|\n)</ul>~i""</li>$1</ul>"$subject);
                            $subject preg_replace("~</li></li>~i""</li>"$subject);
                            $subject preg_replace("~(\r\n)(?!</ul>)~""$1  "$subject);

                            $subject preg_replace_callback("(<(.+?)>)",

                                function (
                            $inhalt) {
                                return 
                            "<".strtolower($inhalt[1]).">";
                                },
                                
                            $subject
                            );

                            echo 
                            "Ausgabe:\n\n".$listen["beginn"], $subject$listen["ende"]."\n\n";

                            /*Ausgabe:

                            <!DOCTYPE html>
                            <html>

                            <head>
                            <title>Test</title>
                            </head>

                            <body>
                            <h1>Test mit Liste</h1>
                            <ul>
                              <li><strong>1 Gewicht: 295 g</strong> </li>
                              <li><strong>2 Obermaterial aus Airmesh</strong> verbessert
                              und der Listeneintrag erstreckt sich über mehrere Zeilen
                              und noch eine Zeile mehr oder so.</li>
                              <li><strong>3 dsfsdfds dsfsdfsd</strong> </li>
                              <li><strong>4 Obermaterial aus Airmesh</strong> verbessert</li>
                            </ul>
                            <p>Schlusszeile</p>
                            </body>
                            </html>
                            */
                            ?>
                            Zuletzt geändert von Melewo; 20.04.2013, 21:16.

                            Kommentar

                            Lädt...
                            X