heinetz: str_replace gegen preg_replace

Beitrag lesen

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