Mario: Regex gesucht table2array

Hi,

ich suche eine Regex um Tabellen in ein array zu wandeln.

http://www.regex-tester.de/uc_574_de.html

Wie man sieht gelingt mir das nicht wirklich gut. Am Ende soll ein Array entstehen mit den tr als neues array und den td als werten des tr-arrays:

Array
(
//tr-1    [0] => Array
           (
            [0] => td-wert-1
            [1] => td-wert-2
            )

//tr-2    [1] => Array
           (
            [0] => td-wert-1
            [1] => td-wert-2
            )
)

Einzig Verlass ist auf die <tr> die <td> sind zwar in einer Zeile immer in gleicher Anzahl, aber je nach Tabelle variabel. Also die Tabelle könnte 2,3,4,5,usw Spalten enthalten. Auch die Struktur kann variabel sein, will sagen die Werte in den Spalten könnten Leerzeichen und Zeilenumbrüche enthalten.

Aber keine Ahnung das zu bewerkstelligen, bin schon fast soweit das mit PHP-Stringfunktionen zu lösen. Ein Ansatz oder noch bessser eine fertige Regex(ja ich weiss das nennt sich Self hier, aber niemand kann auf allen Gebieten ausreichend bewandert sein, deshalb finde ich es hin und wieder auch schön mal fertige Sachen hier zu finden)?

Mario

  1. Aber keine Ahnung das zu bewerkstelligen, bin schon fast soweit das mit PHP-Stringfunktionen zu lösen. Ein Ansatz oder noch bessser eine fertige Regex(ja ich weiss das nennt sich Self hier, aber niemand kann auf allen Gebieten ausreichend bewandert sein, deshalb finde ich es hin und wieder auch schön mal fertige Sachen hier zu finden)?

    in erster linie: zitat 1418

    in zweiter linie solltest du dich mit einem xml-parser auseinandersetzen - zb simplexml - dein html-schnipsel ist nichts anderes als ein sgml-schnipsel (der mit hoher wahrscheinlichkeit wohlgeformtes xml darstellt)

    1. Hi,

      in erster linie: zitat 1418

      Keine Zugangsberechtigung

      in zweiter linie solltest du dich mit einem xml-parser auseinandersetzen - zb simplexml - dein html-schnipsel ist nichts anderes als ein sgml-schnipsel (der mit hoher wahrscheinlichkeit wohlgeformtes xml darstellt)

      Ich benutze simplexml sogar recht häufig und gehe auch davon aus das dieses funktionieren würde, aber genau darum geht es, ich möchte ein unabhängige Lösung.

      Mario

      1. Keine Zugangsberechtigung

        zitat 1418

        Ich benutze simplexml sogar recht häufig und gehe auch davon aus das dieses funktionieren würde, aber genau darum geht es, ich möchte ein unabhängige Lösung.

        bei regulären ausdrücken bist du zb von PCRE-funktionen abhängig, bei simplexml von der simlexml-erweiterungen

        beide sind standardmäßig aktiviert - wo ist das problem?

        1. Ich benutze simplexml sogar recht häufig und gehe auch davon aus das dieses funktionieren würde, aber genau darum geht es, ich möchte ein unabhängige Lösung.

          bei regulären ausdrücken bist du zb von PCRE-funktionen abhängig, bei simplexml von der simlexml-erweiterungen

          beide sind standardmäßig aktiviert - wo ist das problem?

          standardmäßig aktiviert? Bei PHP4?

          Und im Übrigen, ich suche auch keine alternative lediglich eine regex.

          Mario

          1. standardmäßig aktiviert? Bei PHP4?

            bei php 4 ist beides nicht aktiviert - die letzte stabile version von php 4 wurde mitte 2001 veröffentlicht, in diesem fall wäre ohnehin ein update angeraten - zumindest auf die php 4.4 schiene, besser aber gleich auf die aktuelle schiene (5.2)

            software die über 5 jahre alt ist, sollte man nicht mehr einsetzen (zumindest nicht online/live) das ist imho grob fahrlässig

            Und im Übrigen, ich suche auch keine alternative lediglich eine regex.

            im ausgangsposting hast du erwähnt, dass du stringoperationen als alternative in betracht ziehst - jetzt willst du keine alternative mehr, entscheide dich bitte

            wenn du einen regulären ausdruck suchst, fix fertig (vorgekaut), bist du hier gewöhnlicherweise falsch - du kannst aber gerne mit folgendem muster beginnen eine zeile zu matchen, preg_match_all() wäre übrigens ein anfang:

            <tr>(.*)</tr>

            achte darauf, dass die suche nicht zu gierig ist - du willst ja nur eine zeile - ebenso solltest du ggf attribute in betracht ziehen, oder eigenheiten in der sgml/xml-syntax

              
            <tr><td>foo</td></tr>
            ~~~ ist genauso gültig wie `<tr       ><td>foo</td></tr>`{:.language-html}  
              
            das macht den regulären ausdruck schnell kompliziert und unübersichtlich  
              
            man kann schrauben übrigens auch mit einem hammer in die wand schlagen - entweder man nutzt dafür spezielle schrauben (schraubnägel[1]) oder das richtige werkzeug[2] (schraubendreher)  
              
            [1] bereinigten code, der einfach auslesbar ist  
            [2] einen xml-parser der genau für diesen zweck gedacht ist
            
            1. standardmäßig aktiviert? Bei PHP4?
              bei php 4 ist beides nicht aktiviert

              software die über 5 jahre alt ist, sollte man nicht mehr einsetzen (zumindest nicht online/live) das ist imho grob fahrlässig

              Mit PHP4 meine ich < PHP5 und da hat man nicht immer die freie Auswahl.

              im ausgangsposting hast du erwähnt, dass du stringoperationen als alternative in betracht ziehst - jetzt willst du keine alternative mehr, entscheide dich bitte

              Was bedeutet, das ich dann selbst genug alternativen wüsste, aber keine davon könnte mir eine vernünftige Regex ersetzen.

              wenn du einen regulären ausdruck suchst, fix fertig (vorgekaut), bist du hier gewöhnlicherweise falsch - du kannst aber gerne mit folgendem muster beginnen eine zeile zu matchen, preg_match_all() wäre übrigens ein anfang:

              Ob man dann hier so falsch ist, weiss ich nicht, schliesslich finden sich ja auch hier schon mal so manche Schnipsel.

              <tr>(.*)</tr>

              Auf der Basis habe ich das probiert: <tr>.*<.*td.*>(.*)<.*<.*/td.*</tr>

              Aber vom gewünschten Ziel bin ich dann noch weit entfernt.

              [1] bereinigten code, der einfach auslesbar ist

              Darauf kabe ich aber nicht unbedingt Einfluss.

              [2] einen xml-parser der genau für diesen zweck gedacht ist

              Wenn ich simplexml nicht nutzen kann, bleiben nur Classen wie SAX oder sonstwas, wäre dann aber eher Kanonenkugeln => Spatzen.

              Mario

              1. Auf der Basis habe ich das probiert: <tr>.*<.*td.*>(.*)<.*<.*/td.*</tr>

                klein anfangen ist ggf schlauer - matche zuerst die zeilen, dann die zellen - du sagst ja selbst, dass die zellenzahl variable ist

                obriger ausdruck trifft auf alles mögliche zu, ist imho aber ziemlich unsinnig

                der wurde auch auch auf <tr>foo<bartdbaz>inhalt<foo<bar/tdbaz></tr> matchen - und das willst du sicher nicht

                wie gesagt: matche eine zeile und matche dann innerhalb der zeilen die zellen - nichts überstürzen

                Wenn ich simplexml nicht nutzen kann, bleiben nur Classen wie SAX oder sonstwas, wäre dann aber eher Kanonenkugeln => Spatzen.

                eine alternative zu simplexml wäre noch der xmlreader (ab php 5.0 in pecl enthalten)

                ab php 4.x stehen immerhin die xml parser funktionen zur verfügung

                1. klein anfangen ist ggf schlauer - matche zuerst die zeilen, dann die zellen - du sagst ja selbst, dass die zellenzahl variable ist

                  Das habe ich ja versucht:
                  '#<tr.*>(.*)</tr.*>#isU'

                  wie gesagt: matche eine zeile und matche dann innerhalb der zeilen die zellen - nichts überstürzen

                  Ich bekomme jetzt natürlich alles was in den Zeilen steht, aber wie man jetzt daraus einen Substring findet, eben innerhalb der Zellen in den Zeilen, ist mir schleierhaft. Ganz zu schweigen von den anderen Problematiken, Zeilenumbrüche und Leerzeichen.

                  Ich habe mittlerweile hier einen anderen Post dazu gefunden, der sich aber anscheinend nichtauf meine tabelle anwenden lässt:
                  http://forum.de.selfhtml.org/archiv/2008/12/t180347/#m1191318

                  Mario

                  1. Das habe ich ja versucht:
                    '#<tr.*>(.*)</tr.*>#isU'

                    der hintere teil matcht ja schon wieder auf </tr> oder </trfoobarbaz> - das ist denke ich nicht gewünscht

                    das ergebnis mit zb preg_match_all sollte jetzt ein array sein in dem der inhalt deiner zeilen der tabelle drin steht

                    dieses array gehst du mir foreach durch und matcht diesmal halt nach <td>xxx</td>

                    damit erzeugst du dir dann ein mehrdimensionales array gemäß deiner tabellenstruktur

                    Ich bekomme jetzt natürlich alles was in den Zeilen steht, aber wie man jetzt daraus einen Substring findet, eben innerhalb der Zellen in den Zeilen, ist mir schleierhaft. Ganz zu schweigen von den anderen Problematiken, Zeilenumbrüche und Leerzeichen.

                    siehe oben

                    1. Das habe ich ja versucht:
                      '#<tr.*>(.*)</tr.*>#isU'

                      der hintere teil matcht ja schon wieder auf </tr> oder </trfoobarbaz> - das ist denke ich nicht gewünscht

                      Doch eigentlich ist das gewünscht, falls sich dort ein leerzeichen befindet
                      </tr >. Ich weiss nicht ob ich den Abschluss > weglaasen kann damm würde natürlich auch das gehen:
                      '#<tr.*>(.*)</tr#isU'

                      das ergebnis mit zb preg_match_all sollte jetzt ein array sein in dem der inhalt deiner zeilen der tabelle drin steht

                      Natürlich

                      dieses array gehst du mir foreach durch und matcht diesmal halt nach <td>xxx</td>

                      Und genau das kann es doch nicht sein. Dann kann ich ja gleich auf die Regex verzichten explode('<tr',$table)

                      damit erzeugst du dir dann ein mehrdimensionales array gemäß deiner tabellenstruktur

                      Das muss doch allein durch eine Regex zu lösen sein, oder doch nicht?

                      Mario

                      1. Das muss doch allein durch eine Regex zu lösen sein, oder doch nicht?

                        sowas in der richtung, nicht getestet:
                        (<(tr|td)[^>]*>)(.*)(</\2>)

                        sollte auf beliebige vorkommen von tr- oder td-elemente (start-tag, end-tag und inhalt separat) matchen

                        1. Das muss doch allein durch eine Regex zu lösen sein, oder doch nicht?

                          sowas in der richtung, nicht getestet:
                          (<(tr|td)[^>]*>)(.*)(</\2>)

                          sollte auf beliebige vorkommen von tr- oder td-elemente (start-tag, end-tag und inhalt separat) matchen

                          Leider nein: http://www.regex-tester.de/uc_575_de.html

                          Mario

                          1. (<(tr|td)[^>]*>)(.*)(</\2>)
                            Leider nein: http://www.regex-tester.de/uc_575_de.html

                            scheinbar kapiert der keine backreferences, naja dann versuchs mal so:
                            <(tr|td)[^>]*>(.*)</(tr|td)>

                            wie bereits erwähnt ist das verarbeiten der ausgelesenen daten dann sehr verwirrend - ich plädiere immer noch auf einen ordentlichen parser :)

                            1. scheinbar kapiert der keine backreferences, naja dann versuchs mal so:
                              <(tr|td)[^>]*>(.*)</(tr|td)>

                              Danke für deine Mühe: http://www.regex-tester.de/uc_576_de.html
                              aber so richtig sauber ist das auch leider nicht.

                              Nach allem was ich bis jetzt gelesen habe muss das wohl irgendwie mit subpattern gelöst werden also sowas (?:) in der Art. Aber keine Ahnung wie sowas funktioniert.

                              wie bereits erwähnt ist das verarbeiten der ausgelesenen daten dann sehr verwirrend - ich plädiere immer noch auf einen ordentlichen parser :)

                              Auch wenn ich mich auf PHP5 verlassen könnte, ist jetzt alleine die Neugierde schon gross genug, ob das überhaupt geht.

                              Mario

                              1. Auch wenn ich mich auf PHP5 verlassen könnte, ist jetzt alleine die Neugierde schon gross genug, ob das überhaupt geht.

                                vermutlich geht das - man kann auch daten aus einer nicht normalisierten datenbank rauslesen, bei joins tut man sich dann etwas schwer - oder ein brett mit einer bohrmaschine kürzen, hier wirds mit dem geraden schnitt aber etwas unpraktisch :)