Lieber Matze,
Reicht es in dem Fall nicht, alle Elemente zu entfernen die nicht <ul> oder <li> sind? Inklusive HTML, Body und Doctype?
das "Entfernen" ist so eine Sache. Du willst zwar manche Elemente _komplett_ entfernen, bei anderen Elementen (z.B. <body>) möchtest Du nur die Tags entfernen, den Inhalt aber erhalten.
$html = preg_replace('(?s<
Das ist ein Syntaxfehler. (?s) ist ein Schalter in der PCRE-Schreibweise, der Zeilenumbrüche mit einschließt, sodass der String in Gänze behandelt wird.
(!DOCTYPE|html|body|address|...
Hier haben wir eine ODER-verknüpfte Liste mit festen (alternativen) Zeichenfolgen, die nach diesem Schema aufgebaut ist: (erstens|zeitens|drittens)
Die Klammerung bedeutet nicht nur, dass der Klammerninhalt als "ODER-Liste" zu verstehen ist, sondern bewirkt auch, dass der Inhalt "gemerkt" wird, um ihn später als Referenz wieder zu benutzen.
~Er (war|ist) davon überzeugt, dass auch sie davon in Kenntnis gesetzt \1.~
Dieses Muster passt auf folgende zwei Sätze:
- Er ist davon überzeugt, dass auch sie davon in Kenntnis gesetzt ist.
- Er war davon überzeugt, dass auch sie davon in Kenntnis gesetzt war.
Das Muster passt aber nicht auf folgende Sätze:
- Er ist davon überzeugt, dass auch sie davon in Kenntnis gesetzt war.
- Er war davon überzeugt, dass auch sie davon in Kenntnis gesetzt ist.
Der Ausdruck in Klammern wird "gemerkt". Da es die erste Klammer im Muster ist, kann man ihren Inhalt mit \1 referenzieren.
<(!DOCTYPE|html|body|...|textarea|tt|var)>.*?</\1>
Das wird schiefgehen. Du ignorierst mit dieser Schreibweise, dass Elemente im öffnenden Tag auch Attribute haben können (denke an Deine Klassen!). Und Du setzt ein schließendes Tag ebenfalls voraus, was nicht in allen Fällen (denke an den Doctype!) existiert. Gerade bei <br />/<hr />, <meta /> und <img /> hast Du in XHTML auch selbstschließende Elemente, die per Definition inhaltsleer sind. Auch diese bekommst Du so nicht entfernt.
Besser (aber noch immer nicht gut):
<(!DOCTYPE|html|...)( [^>]*)?>.*?</\1>
Durch das Fragezeichen nach der zweiten Klammer wird eventuell Folgendes mit berücksichtigt. Wenn es fehlt ist das trotzdem ein Treffer. Der Inhalt der zweiten Klammer wird auch "gemerkt", auch wenn wir ihn nirgendwo mehr referenzieren. Bei unserem Muster ist das von der Performance her auch OK. Wenn Du das abstellen wolltest, um z.B. bei komplexeren Mustern Speicher zu sparen, dann könntest Du an den Anfang der zweiten Klammer ?: notieren, was das "Merken" abstellt:
<(!DOCTYPE|html|...)(?: [^>]*)?>.*?</\1>
Das Muster wird Dich aber mit seiner Wirkungsweise enttäuschen. Zum Beispiel würde <html>.*?</html> das komplette Dokument leeren, da Du den Inhalt des <html>-Elementes ebenso wie seine umschließenden Tags durch einen leeren String ersetzen lässt. Damit hast Du dann Dein Ziel endgültig nicht erreicht... Vergiss nicht, was Du erhalten willst, und wie und wo es im XHTML-Dokument notiert ist (Elternelemente usw.)!
Meine mehrstufige Vorgehensweise hatte durchaus ihren Grund - der Dir jetzt vielleicht auch einleuchtet. Dieses "tag soup parsing" ist nicht trivial. Der Gebrauch von regulären Ausdrücken ist zum Parsen auch nicht das geeignete Werkzeug. Jedoch wollten wir ja nur einen bestehenden String von unerwünschten Bestandteilen säubern. Aber da das eben nicht trivial ist, wir aber aufgrund diverser Rahmenbedingungen gewisse Möglichkeiten von vorneherein ausschließen können (z.B. <li>-Elemente enthalten nur Textknoten und keine weiteren HTML-Elemente als Kindelemente), ist ein Vorgehen mit regulären Ausdrücken tatsächlich überhaupt sinnvoll.
Liebe Grüße,
Felix Riesterer.
--
ie:% br:> fl:| va:) ls:[ fo:) rl:° n4:? de:> ss:| ch:? js:) mo:} zu:)