Franz Handlos: HTML-Tabelle mit RegExp auslesen

Guten Abend,

ich möchte mittels eines regulären Ausdrucks den Zelleninhalt einer HTML-Tabelle auslesen. Die entsprechende Tabelle besitzt lediglich eine Spalte, allerdings beliebig viele Zeilen.

<table>
<tr><td>Wert X</td></tr>
<tr><td>Wert Y</td></tr>
<tr><td>Wert Z</td></tr>
...
</table>

Mein regulärer Ausdruck, der die Zelleninhalte auslesen soll sieht folgendermassen aus:

<table>(?:<tr><td>([^<]*)</td></tr>)+</table>

Seltsamerweisse wird nur der Zelleninhalt der letzten Zelle (im Bsp: Wert Z) gematched, alle anderen Zellen werden scheinbar nicht gefunden. Was muss ich ändern, damit der Ausdruck auf jede Zeile der Tabelle angewandt wird?

Grüsse,
Franz

  1. Seltsamerweisse wird nur der Zelleninhalt der letzten Zelle (im Bsp: Wert Z) gematched, alle anderen Zellen werden scheinbar nicht gefunden. Was muss ich ändern, damit der Ausdruck auf jede Zeile der Tabelle angewandt wird?

    Was für ein Ergebniss erwartest du eigentlich? Einen Array mit den Texten der jeweiligen Tabellenzeilen oder vielleicht einen String, in dem der Inhalt aller Tabellenzeilen aneinandergehängt wird?

    (?:<tr><td>([^<]*)</td></tr>)+

    Das '+' am Ende dieses Regexschnipsels sorgt dafür, dass das, was in der Klammer steht, mindestens einmal ausgeführt wird. D.h. zuerst matched der Regex '<tr><td>' dann kommt ein Subpattern, der auf alle Möglichen Zeichen außer '<' matched, dann wird der Subpattern in einer Variable gespeichert. Schlussendlich wird dann noch auf '</td></tr>' gematcht und das was in der Klammer, wenn möglich, noch einmal ausgeführt. Bei jedem Durchgang des Klammerninhalts wird der darin enthaltene Subpattern ausgeführt und immer IN DER SELBEN VARIABLE gespeichert. So ergibt es sich, dass am Ende nur der Inhalt der letzten Tabellenzeile in der Subpatternvariable steht.

    mfg
    Rato

    --
    §§§
    Meine Postings basieren lediglich auf mein Wissen und können völliger Blödsinn sein.
    §§§
    1. Was für ein Ergebniss erwartest du eigentlich? Einen Array mit den Texten der jeweiligen Tabellenzeilen oder vielleicht einen String, in dem der Inhalt aller Tabellenzeilen aneinandergehängt wird?

      Eigentlich erwarte ich ein mehrdimensionales Array, in dem alle(!) Zellenwerte gespeichert sind, nicht nur das Letzte, weil dieses die vorigen Treffer wieder überschreibt!

      Kannst du mir eine Lösung für mein Problem vorschlagen?

      Grüsse,
      Franz

      1. Hi,

        Was für ein Ergebniss erwartest du eigentlich? Einen Array mit den Texten der jeweiligen Tabellenzeilen oder vielleicht einen String, in dem der Inhalt aller Tabellenzeilen aneinandergehängt wird?

        Eigentlich erwarte ich ein mehrdimensionales Array,

        Wo sollten mehrere Dimensionen herkommen?

        Es findet genau ein Match statt (<table>(?:<tr><td>([^<]*)</td></tr>)+</table> muß ja das öffnende und schließende Tag von table matchen, diese sind nur einmal vorhanden, also gibt es nur ein match).
        Und Dein Ausdruck enthält nur eine einzige capturing () - also wird bei dem einen match auch nur ein substring gefunden.

        cu,
        Andreas

        --
        Warum nennt sich Andreas hier MudGuard?
        O o ostern ...
        Fachfragen unaufgefordert per E-Mail halte ich für unverschämt und werde entsprechende E-Mails nicht beantworten. Für Fachfragen ist das Forum da.
        1. Es findet genau ein Match statt (<table>(?:<tr><td>([^<]*)</td></tr>)+</table> muß ja das öffnende und schließende Tag von table matchen, diese sind nur einmal vorhanden, also gibt es nur ein match).

          Das Table-Tag soll ja nicht gematched werden, lediglich der Zelleninhalt darin. Da dachte ich, man könne mit regulären so nahezu alles machen, nun kann ich eine simple Tabelle nicht mal mit einem Pattern auslesen lassen. Irgendwie ist mein Weltbild getrübt...

          1. Das Table-Tag soll ja nicht gematched werden, lediglich der Zelleninhalt darin.

            Dann reduziere Deinen Ausdruck doch genau darauf.

            1. Dann reduziere Deinen Ausdruck doch genau darauf.

              Ich möchte sicherstellen, dass die Zelle in dieser Tabelle und nicht in einer anderen Tabelle vorhanden sind. Sonst würde der RegExp auch Zelleninhalte der vrogien Tabelle matchen!

              1. Ich möchte sicherstellen, dass die Zelle in dieser Tabelle und nicht in einer anderen Tabelle vorhanden sind.

                Dann kannst Du sicherstellen, daß das Ergebnis nur aus der gewünschten
                Tabelle bezogen wird, indem Du nach eindeutigen Charakteristika suchen
                lässt; diese könnten entweder im Aufbau des gesuchten Wertes selbst,
                oder in der Syntax/Auszeichnung der umliegenden Tabellenelemente zu
                finden sein. Irgendwelche reproduzierbaren Gemeinsamkeiten (bzw.
                Unterschiede) sollte es schon geben, ansonsten wird es schwierig, die
                Aufgabe allein mit Regulären Ausdrücken zu lösen.

                1. Dann kannst Du sicherstellen, daß das Ergebnis nur aus der gewünschten
                  Tabelle bezogen wird, indem Du nach eindeutigen Charakteristika suchen
                  lässt; diese könnten entweder im Aufbau des gesuchten Wertes selbst,
                  oder in der Syntax/Auszeichnung der umliegenden Tabellenelemente zu
                  finden sein. Irgendwelche reproduzierbaren Gemeinsamkeiten (bzw.
                  Unterschiede) sollte es schon geben, ansonsten wird es schwierig, die
                  Aufgabe allein mit Regulären Ausdrücken zu lösen.

                  Leider liegt das einzig eindeutige Merkmal der Tabelle im Table-Tag selber, da dort eine bestimmte CSS-Klasse hinterlegt ist. Der "innere Teil", also Zeilen und Zellen sind nicht von anderen Tabellen zu unterscheiden..

                  1. Leider liegt das einzig eindeutige Merkmal der Tabelle im Table-Tag selber, [...]

                    In welchem Kontext (Produktionsumgebung, administrativ etc.) und in
                    welcher Umgebung (Skript/Programmiersprache, Konsole (+OS) usw.) soll
                    der Ausdruck ausgeführt werden? Die Implementierungen unterscheiden
                    sich teils beträchtlich.

                    1. In welchem Kontext (Produktionsumgebung, administrativ etc.) und in
                      welcher Umgebung (Skript/Programmiersprache, Konsole (+OS) usw.) soll
                      der Ausdruck ausgeführt werden? Die Implementierungen unterscheiden
                      sich teils beträchtlich.

                      Eine Webanwendung eines Kunden generiert aus Motorkenndaten bis dato statische Webseiten. Durch ein PHP-Script sollen die Daten einer solchen Datei eingelesen und auf einer Seite im Intranet angezeigt werden. Mittels preg_match_all() sollen die Informationen aus den HTML-Dateien ausgelesen werden. Alle im HTML vorhandenen Tabellen unterscheiden sich nicht lediglich im Table-Tag - da jede Tabelle dynamisch viele Spalten besitzt und ich keine festen Werte als Anhaltspunkte besitze, kann ich meine suche nicht anders einschränken...

                      1. [...] statische Webseiten. Durch ein PHP-Script sollen die Daten einer solchen Datei eingelesen und auf einer Seite im Intranet angezeigt werden. Mittels preg_match_all() sollen die Informationen aus den HTML-Dateien ausgelesen werden. [...]

                        Schade eigentlich; mittels "Lookbehinds" dynamischer Länge liesse sich
                        die Aufgabenstellung mit einem einzelnen Regulären Ausdruck lösen - dies
                        wird allerdings von PHP (noch) nicht unterstützt. Innerhalb von PHP
                        wirst Du deshalb um mindestens zwei Schritte nicht herum kommen: a), die
                        richtige Tabelle zu identifizieren und b), die gewünschten Daten zu
                        extrahieren. Beispiel:

                        $html = '
                            <table class="negativ">
                            <tr><td>will ich nicht</td></tr>
                            </table>

                        <p>bla bla</p>

                        <table class="positiv">
                            <tr><td>will ich haben</td></tr>
                            <tr><td>will ich auch haben</td></tr>
                            <tr><td>dito</td></tr>
                            </table>
                        ';

                        preg_match(
                            '-(?><table[^>]+class="positiv"[^>]*+>)(?>\s*<tr>\s*<td>[^<]*</td>\s*</tr>)*-i',
                            $html,
                            $tabelle
                        );

                        preg_match_all(
                            '-(?<=<td>)[^<]*(?=</td>)-i',
                            $tabelle[0],
                            $werte
                        );

                        print_r( $werte );

      2. Eigentlich erwarte ich ein mehrdimensionales Array, in dem alle(!) Zellenwerte gespeichert sind, nicht nur das Letzte, weil dieses die vorigen Treffer wieder überschreibt!

        Kannst du mir eine Lösung für mein Problem vorschlagen?

        Mein Vorschlag:
        Als erstes wendest du den von dir geposteten Regex auf die jeweilige Datei an, dann wendest du auf das Gesamtergebnis dieses Regex (= die ganze Tabelle von <table> bis </table>) einen weiteren Regex an:

        <tr><td>([^<]*)</tr></td>

        Du hast zwar nicht geschrieben, in welcher Programmiersprache du das machst, aber falls es PHP ist, verwendest du die Function preg_match_all. Die liefert dir alle möglichen Ergebnisse des Regex in dem zu durchsuchenden String. Jetzt hast du leicht Zugriff auf den gewünschten Subpattern, denn preg_match_all liefert einen mehrdimensionalen Array zurück. siehe das PHP-Handbuch der Entwickler auf php.net

        mfg
        Rato

        --
        §§§
        Meine Postings basieren lediglich auf mein Wissen und können völliger Blödsinn sein.
        §§§