heinetz: str_replace gegen preg_replace

Hallo Forum,

ich habe eine Zeichenkette, in der HTML-Code steht. Diese Zeichenkette
möchte ich in ein Array verwandeln. Dazu wird die Zeichenkette erstmal
geparsed:

$old = str_replace("\n", "", $old);  
 $old = str_replace("\r", "", $old);  
 echo "2:".$old."\n\n";  
  
 $old = str_replace(">", ">\n", $old);  
 $old = str_replace("<", "\n<", $old);  
 $old = str_replace("\n\n", "\n", $old);

Damit erreiche ich, dass alle Tags in einzelnen Zeilen stehen und so wird
aus:

<h1>Tolle Überschrift</h1>  
<p>Das ist ein toller Absatz.</p>
<h1>  
Tolle Überschrift  
</h1>  
<p>  
Das ist ein toller Absatz.  
</p>

Mit str_replace denke ich, ist das nicht wirklich elegent gelöst und ich
versuceh das ganze durch preg_replace zu ersetzen. Für den ersten Teil
habe ich das auch hinbekommen:

  
$old = preg_replace("/\r\n|\n\r|\n|\r/", "", $old);

Für den zweiten Teil fällt mir allerdings nicht ein, wie das gehen sollte.

Hat jemand einen Tipp

beste gruesse,
heinetz

  1. Hi,

    Mit str_replace denke ich, ist das nicht wirklich elegent gelöst

    warum nicht?

    Für den zweiten Teil fällt mir allerdings nicht ein, wie das gehen sollte.

    Welchen Vorteil versprichst Du Dir speziell an der Stellee von Regular Expressions?

    Cheatah

    --
    X-Self-Code: sh:( fo:} ch:~ rl:| br:> n4:& ie:% mo:) va:) de:] zu:) fl:{ ss:) ls:~ js:|
    X-Self-Code-Url: http://emmanuel.dammerer.at/selfcode.html
    X-Will-Answer-Email: No
    X-Please-Search-Archive-First: Absolutely Yes
  2. Moin!

    Für den ersten Teil habe ich das auch hinbekommen:

    » $old = preg_replace("/\r\n|\n\r|\n|\r/", "", $old);

    Du willst alle Zeileumbrüche löschen:
    » $old = preg_replace("/\r|\n/", "", $old);

    oder $str=str_replace(array("\r", "\n"),'', $str);

    $old = str_replace(">", ">\n", $old);
    $old = str_replace("<", "\n<", $old);

    (Das kenne ich doch... Bitte bleibe das nächste Mal in Deinem Thread.)

    Für den zweiten Teil fällt mir allerdings nicht ein, wie das gehen sollte.

    Du willst beliebig aufeinander folgenden Zeilenumbrüche durch genau einen ersetzen

    <?php  
    $s="bar\n\nfoo\n\nblabla\n\n\nbar";  
    echo preg_replace("/\n+/", "\n",$s);  
    ?>
    

    MFFG (Mit freundlich- friedfertigem Grinsen)

    fastix

    1. Moin!

      Und als Einzeiler:

      $old = preg_replace( "/\n+/", "\n", str_replace(array ("<", ">"), array ("\n<", ">\n"), $old) );

      Das vorherige Löschen der Zeilenumbrüche in den Texten halte ich für Nonsens.

      MFFG (Mit freundlich- friedfertigem Grinsen)

      fastix

      1. Hallo,

        ok, entschuldigt das Mehrfachposting. Ich hab selbst den Überblick verloren, will versuchen, in einem Thread zu bleiben und hoffe, ich bin hier nun richtig.

        Und als Einzeiler:

        $old = preg_replace( "/\n+/", "\n", str_replace(array ("<", ">"), array ("\n<", ">\n"), $old) );

        Danke für den Einzeiler! Den habe ich an zwei Stellen ergänzt:

        $html = trim(preg_replace( "/\n+/", "\n", str_replace(array ("<", ">"), array ("\n<", ">\n"), str_replace(array("\r", "\n"),"\n", $html))));

        1. Vor dem Einfügen von "/n" vor "<" und nach ">" ersetze ich alle "/r" gegen "/n" und

        2. abschliessend entledige ich mich der überflüssig eingesetzen "\n" vor em ersten "<" bzw. nach dem letzten ">".

        Danach habe ich meinen HTML-String als Arry, wie ich es benötige. Was ich überhaupt machen möchte habe ich in meinem ersten Thread versucht zu beschreiben. Nun habe ich also zwei HTML-Strings zu HTML-Arrays gemacht und die werden verglichen. Das funktioniert grundsätzlich. Bis hierher habe ich für den Vergleich dieses einfach gehaltene Skript von Paul Butler benutzt und bin dabei auf folgende grundsätzliche Schwierigkeit gestossen:

        Ich vergleiche diese beiden Strings:

        <div class="infobox_orange">
        <h4>Liste:<strong>&nbsp;</strong></h4>
        <ul>
        <li><strong>Erster Listeeneintrag</strong> <a href="www1.example.org">weiter</a></li>
        <li><strong>Zweiter Listeeneintrag</strong> <a href="www2.example.org">weiter</a></li>
        <li><strong>Dritter Listeeneintrag</strong> <a href="www3.example.org">weiter</a></li>
        </ul>
        </div>
        
        <div class="infobox_orange">
        <h4>Liste:<strong>&nbsp;</strong></h4>
        <ul>
        <li><strong>Erster Listeeneintrag</strong> <a href="www1.example.org">weiter</a></li>
        <li><strong>Dritter Listeeneintrag</strong> <a href="www3.example.org">weiter</a></li>
        </ul>
        </div>
        

        ... bzw die beiden daraus entstandenden Arrays:

        Array
        (
            [0] => <div class="infobox_orange">
            [1] => <h4>
            [2] => Liste:
            [3] => <strong>
            [4] => &nbsp;
            [5] => </strong>
            [6] => </h4>
            [7] => <ul>
            [8] => <li>
            [9] => <strong>
            [10] => Erster
            [11] => Listeeneintrag
            [12] => </strong>
            [13] =>
            [14] =>
            [15] => <a href="www1.example.org">
            [16] => weiter
            [17] => </a>
            [18] => </li>
            [19] => <li>
            [20] => <strong>
            [21] => Zweiter
            [22] => Listeeneintrag
            [23] => </strong>
            [24] =>
            [25] =>
            [26] => <a href="www2.example.org">
            [27] => weiter
            [28] => </a>
            [29] => </li>
            [30] => <li>
            [31] => <strong>
            [32] => Dritter
            [33] => Listeeneintrag
            [34] => </strong>
            [35] =>
            [36] =>
            [37] => <a href="www3.example.org">
            [38] => weiter
            [39] => </a>
            [40] => </li>
            [41] => </ul>
            [42] => </div>
        )
        
        Array
        (
            [0] => <div class="infobox_orange">
            [1] => <h4>
            [2] => Liste:
            [3] => <strong>
            [4] => &nbsp;
            [5] => </strong>
            [6] => </h4>
            [7] => <ul>
            [8] => <li>
            [9] => <strong>
            [10] => Erster
            [11] => Listeeneintrag
            [12] => </strong>
            [13] =>
            [14] =>
            [15] => <a href="www1.example.org">
            [16] => weiter
            [17] => </a>
            [18] => </li>
            [19] => <li>
            [20] => <strong>
            [21] => Dritter
            [22] => Listeeneintrag
            [23] => </strong>
            [24] =>
            [25] =>
            [26] => <a href="www3.example.org">
            [27] => weiter
            [28] => </a>
            [29] => </li>
            [30] => </ul>
            [31] => </div>
        )
        
        

        Das Ergebnis des Vergleichs ist wieder ein Array ($diff):

        Array
        (
            [0] => Array
                (
                    [d] => Array
                        (
                        )
        
                    [i] => Array
                        (
                        )
        
                )
        
            [1] => <div class="infobox_orange">
            [2] => <h4>
            [3] => Liste:
            [4] => <strong>
            [5] => &nbsp;
            [6] => </strong>
            [7] => </h4>
            [8] => <ul>
            [9] => <li>
            [10] => <strong>
            [11] => Erster
            [12] => Listeeneintrag
            [13] => </strong>
            [14] =>
            [15] =>
            [16] => <a href="www1.example.org">
            [17] => weiter
            [18] => </a>
            [19] => </li>
            [20] => <li>
            [21] => <strong>
            [22] => Array
                (
                    [d] => Array
                        (
                            [0] => Zweiter
                            [1] => Listeeneintrag
                            [2] => </strong>
                            [3] =>
                            [4] =>
                            [5] => <a href="www2.example.org">
                            [6] => weiter
                            [7] => </a>
                            [8] => </li>
                            [9] => <li>
                            [10] => <strong>
                        )
        
                    [i] => Array
                        (
                        )
        
                )
        
            [23] => Dritter
            [24] => Listeeneintrag
            [25] => </strong>
            [26] =>
            [27] =>
            [28] => <a href="www3.example.org">
            [29] => weiter
            [30] => </a>
            [31] => </li>
            [32] => </ul>
            [33] => </div>
        )
        

        ... und daran wird ersichtlich, was passiert:

        Ich habe den zweiten Listeneintrag gelöscht, also:

        <li><strong>Zweiter Listeeneintrag</strong> <a href="www2.example.org">weiter</a></li>

        Im Vergleich der beiden Arrays ist sind aber alle Elemente bis [20] gleich und entspechens der Logik ist der gelöschte Teilstring folgender:

        Zweiter Listeeneintrag</strong> <a href="www2.example.org">weiter</a></li><li><strong>

        Wie geht man damit um?

        Ich habe mir zunächt mal eine Funktion gebaut, die in dem Array $diff, das (Unter-)Array ('d', 'i') um n Elemente nach OBEN verschieben kann. Das (Unter-)Array $diff[22] um 2 Elemente nach OBEN verschoben sähe dann so aus:

        Array
        (
            [0] => Array
                (
                    [d] => Array
                        (
                        )
        
                    [i] => Array
                        (
                        )
        
                )
        
            [1] => <div class="infobox_orange">
            [2] => <h4>
            [3] => Liste:
            [4] => <strong>
            [5] => &nbsp;
            [6] => </strong>
            [7] => </h4>
            [8] => <ul>
            [9] => <li>
            [10] => <strong>
            [11] => Erster
            [12] => Listeeneintrag
            [13] => </strong>
            [14] =>
            [15] =>
            [16] => <a href="www1.example.org">
            [17] => weiter
            [18] => </a>
            [19] => </li>
            [20] => Array
                (
                    [d] => Array
                        (
                            [0] => <li>
                            [1] => <strong>
                            [2] => Zweiter
                            [3] => Listeeneintrag
                            [4] => </strong>
                            [5] =>
                            [6] =>
                            [7] => <a href="www2.example.org">
                            [8] => weiter
                            [9] => </a>
                            [10] => </li>
                        )
        
                    [i] => Array
                        (
                        )
        
                )
        
            [21] => <li>
            [22] => <strong>
            [23] => Dritter
            [24] => Listeeneintrag
            [25] => </strong>
            [26] =>
            [27] =>
            [28] => <a href="www3.example.org">
            [29] => weiter
            [30] => </a>
            [31] => </li>
            [32] => </ul>
            [33] => </div>
        )
        

        ... und erscheint richtig. Nur woher nehme ich n? Mein erster Versuch, dieses Verschieben so lange zu machen, bis am Ende des explodeden Arrays keine Tags mehr geöffnet werden ...

        
        while(preg_match("/<[^\/].+>[^><]*/", implode(" ", $diff[$i]['d']))
        
        

        ... haut ganz gut hin. Allerdings fällt mir als nächstes auf, dass in dem Array $diff in einem anderen Beispiel das (Unter-)Array nach unten verschoben werden muss, weil das Skript den Vergleich anders herum vorgenommen hat:

        
            [23] => Dritter
            [24] => Listeeneintrag
            [25] => </strong>
            [26] =>
            [27] =>
            [28] => <a href="www3.example.org">
            [29] => Array
                (
                    [d] => Array
                        (
                            [0] => weiter
                            [1] => </a>
                            [2] => </li>
                            [3] => <li>
                            [4] => <strong>
                            [5] => Vierter
                            [6] => Listeeneintrag
                            [7] => </strong>
                            [8] =>
                            [9] =>
                            [10] => <a href="www4.example.org">
                        )
        
                    [i] => Array
                        (
                        )
        
                )
        
            [30] => weiter
            [31] => </a>
            [32] => </li>
        
        

        Die Funktion, das (Unter-)Array zu verschieben, lässt sich natürlich auch so programmieren, dass es nach UNTEN verschoben wird. Allerdings stellt sich dann die Frage, wann nach oben und wann nach unten verschoben wird.

        Vor Allem aber, und das ist mein Stand im Moment, stelle ich mir die Frage, warum das Skript einmal aus der einen und einmal aus der anderen Richtung vergleicht, ob ich das als Fehler in dem Skript werten und unter Umständen doch mit einer Alternative arbeiten oder ob ich den Weg, das (Unter-)Array nach OBEN und nach UNTEN zu verschieben weitergehen sollte. Ein anderer Ansatz, den ich auch interessant finde, ist das HTML-Array so zu bilden, dass keine "Verwechslungsgefahr" mehr besteht. Konkret wüsste ich aber im Moment noch nicht wie.

        danke für's Zuhören  ;)

        beste gruesse, heinetz

        1. Moin!

          Vor Allem aber, und das ist mein Stand im Moment, stelle ich mir die Frage, warum das Skript einmal aus der einen und einmal aus der anderen Richtung vergleicht,

          Ganz einfach: Es kann Text hinzugefügt worden sein (macht Vergleich nach unten nötig) und es kann gelöscht worden sein (macht Vergleich nach oben nötig).

          Ich würde übrigens alle leeren Array-Elemente löschen (oder besser noch alle auf einander folgenden Zeilenbrüche durch jeweils einen ersetzen):

          Also:

          $html = preg_replace("/\n+/", "\n",(trim(preg_replace( "/\n+/", "\n", str_replace(array ("<", ">"), array ("\n<", ">\n"), str_replace(array("\r", "\n"),"\n", $html)))));

          Leerzeilen dürften für die Differenzbetrachtung ziemlich uninteressant sein.

          MFFG (Mit freundlich- friedfertigem Grinsen)

          fastix

  3. Hat jemand einen Tipp

    Beschreibe, was du überhaupt machen möchtest - ich kann in deinem vorhaben bisher keinen Sinn entdecken.

    Willst du ggf. sämtliche Tags entfernen und musst sie zuvor in jeweils eigene Zeilen packen die du dann nochmals mit einer Schleife durchläufst und analyisierst? Oder bin ich nur paranoid?

    1. Moin!

      Beschreibe, was du überhaupt machen möchtest

      MFFG (Mit freundlich- friedfertigem Grinsen)

      fastix

      1. Beschreibe, was du überhaupt machen möchtest

        Danke - das ist also in die Kategorie "Warum Doppelpostings eine schlechte Idee sind." einzurodnen ;)