REGEX nicht geschlossene <li>

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • 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
    Last edited by tomtherock; 19-04-2013, 11: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] => 
            )
    */ 

    Comment


    • #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 .

      Comment


      • #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
                )

        */ 

        Comment


        • #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>

          Comment


          • #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.
            Last edited by Melewo; 19-04-2013, 15:41.

            Comment


            • #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?

              Comment


              • #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

                Comment


                • #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>

                  */ 
                  Last edited by Melewo; 19-04-2013, 18:42.

                  Comment


                  • #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>

                    */
                    ?>

                    Comment


                    • #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();
                      Last edited by combie; 19-04-2013, 21:03.
                      Wir werden alle sterben

                      Comment


                      • #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.

                        Originally posted by tomtherock View Post
                        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
                        Last edited by Melewo; 20-04-2013, 05:22.

                        Comment


                        • #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?
                          Last edited by combie; 20-04-2013, 05:25.
                          Wir werden alle sterben

                          Comment


                          • #14
                            Originally posted by combie View Post
                            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>
                            */
                            ?>
                            Last edited by Melewo; 20-04-2013, 20:16.

                            Comment

                            Working...
                            X