Ajax / PHP / XML - Tabelle dynamisch generieren

Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

  • Ajax / PHP / XML - Tabelle dynamisch generieren

    Hallo Freunde der .com-Blase,

    folgendes Problem; ich baue mir eine feste Tabellenstruktur auf (mit IDs versehen), und fülle diese Struktur via Ajax bei einer bestimmten Anfrage mit Daten aus einer XML-Datei, wobei die Daten anhand der IDs zugeordnet werden, soweit kein Problem.

    Nun kann eine Anfrage aber verschieden viele Ausgabedaten zurückgeben, also passt das mit der festen Tabellenstruktur nicht mehr.

    Ich habe mir überlegt, dass ich bei Erzeugung der Anfrage durch Selectboxen zunächst die Anzahl der Knoten in der XML-Struktur zähle und daraufhin eine Schleife starte, die mir die Tabellenstruktur mit den benötigten Zeilen erstellt. Doch wie ist das realisierbar?

    Ich poste mal den Code, den ich habe:

    Hier wird die feste Tabellstruktur erzeugt:

    Quellcode

    1. // Feste Tabellenstruktur wird erzeugt
    2. for($i = 1; $i <= 13; $i++) {
    3. echo "<tr id=\"D".$i."\">\n";
    4. echo " <th width=\"20\">\n";
    5. echo " <div class=\"nr\">".$i."</div>\n";
    6. echo " </th>\n";
    7. echo " <td class=\"name\">\n";
    8. echo " <div class=\"name\">--</div>\n";
    9. echo " </td>\n";
    10. echo " <td class=\"type\">\n";
    11. echo " <div class=\"type\">--</div>\n";
    12. echo " </td>\n";
    13. echo "</tr>";
    14. }
    Alles anzeigen



    Hier wird die Anfrage an die Funktion gesendet, die die XML Datei erzeugt

    Quellcode

    1. // Anfrage wird gesendet
    2. echo "<input type=\"submit\" value=\"Auswahl senden\" onclick=\"RequestXML('type','klassisch')\"></div>";



    Hier wird die XML-Datei erzeugt, entsprechend werden die Daten in die feste Tabellenstruktur via Ajax zurückgeschrieben:

    Quellcode

    1. var req;
    2. var response;
    3. function RequestXML(overview, name) {
    4. if (ajax) {
    5. var url = 'creatorExporter.php?overview='+overview+'&name='+name;
    6. if (window.XMLHttpRequest) {
    7. req = new XMLHttpRequest();
    8. req.onreadystatechange = processReqChange;
    9. req.open("GET", url, true);
    10. req.send(null);
    11. } else if (window.ActiveXObject) {
    12. req = new ActiveXObject("Microsoft.XMLHTTP");
    13. if (req) {
    14. req.onreadystatechange = processReqChange;
    15. req.open("GET", url, true);
    16. req.send();
    17. }
    18. }
    19. } else {
    20. // do something
    21. }
    22. }
    23. function processReqChange() {
    24. if (req.readyState == 4) {
    25. if (req.status == 200) {
    26. response = req.responseXML.documentElement;
    27. var campaignNames = response.getElementsByTagName('campaign_name');
    28. for (var j=0; j<campaignNames.length; j++) {
    29. for (var i=0; i<2;i++) {
    30. var id = response.getElementsByTagName('campaign_type').item(j).parentNode.getAttribute('id');
    31. if (document.getElementById(id).getElementsByTagName('td').item(i).className == 'name') {
    32. document.getElementById(id).getElementsByTagName('td').item(i).innerHTML = GetDepthXmlValue('campaign_name', j, '&nbsp;');
    33. }
    34. if (document.getElementById(id).getElementsByTagName('td').item(i).className == 'type') {
    35. document.getElementById(id).getElementsByTagName('td').item(i).innerHTML = GetDepthXmlValue('campaign_type', j, '&nbsp;');
    36. }
    37. }
    38. }
    39. }
    40. }
    41. }
    42. function GetDepthXmlValue(tagName, i, failValue) {
    43. if (response.getElementsByTagName(tagName)) {
    44. if (response.getElementsByTagName(tagName).item(i)) {
    45. if (response.getElementsByTagName(tagName).item(i).firstChild) {
    46. return response.getElementsByTagName(tagName).item(i).firstChild.data;
    47. } else {
    48. return failValue;
    49. }
    50. } else {
    51. return failValue;
    52. }
    53. } else {
    54. return failValue;
    55. }
    56. }
    57. }
    Alles anzeigen


    Wie erzeuge ich die Tabellenstruktur mit den IDs dynamisch entsprechend des Ergebnis-Counts der Anfrage am Elegantesten, was meint Ihr??

    Danke vorab!!
  • Also um ehrlich zu sein, hab ich keine Ahnung von XML.. wenn ich mir die Wikipedia anschaue, dann stelle ich mir deine XML Datei in etwa so vor, wie unten beschrieben vor.
    Man könnte ein "Feld" für die Postings als Zähler benutzen und dessen Inhalt bei jedem Eintrag inkrementieren.
    Denn bei jedem Aufruf die Einträge zu zählen kostet schließlich Performance.

    Vielleicht hab ich das auch falsch verstanden. Könntest du mal die XML Datei anhängen?

    Ein bisschen XML würd mich schon interessieren ;)

    Quellcode

    1. <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    2. <tabelle>
    3. <titel>Deine Tabelle</titel>
    4. <zaehler>5</zaehler>
    5. <contents>
    6. <nr>1</nr>
    7. <name>Titel</name>
    8. <type>Typ</type>
    9. </contents>
    10. <contents>
    11. <nr>1</nr>
    12. <name>Titel</name>
    13. <type>Typ</type>
    14. </contents>
    15. <contents>
    16. <nr>1</nr>
    17. <name>Titel</name>
    18. <type>Typ</type>
    19. </contents>
    20. </tabelle>
    Alles anzeigen
  • Der für den obigen Code relevante Teil des XML-Files sieht so aus:

    Quellcode

    1. <?xml version="1.0" ?>
    2. <!DOCTYPE WebData (View Source for full doctype...)>
    3. <WebData>
    4. <Data id="D1">
    5. <campaign_name>Anzeigen-Streuplan</campaign_name>
    6. <campaign_type>Klassisch</campaign_type>
    7. </Data>
    8. <Data id="D2">
    9. <campaign_name>E-Mail-Marketing</campaign_name>
    10. <campaign_type>Events</campaign_type>
    11. </Data>
    12. </WebData>
    Alles anzeigen


    Wie Du siehst habe ich eine ID für jeden Data-Knoten vergeben.

    Anhand dieser ID wird die Position bestimmt, siehe hier:


    Quellcode

    1. var id = response.getElementsByTagName('campaign_name').item(j).parentNode.getAttribute('id');
    2. if (document.getElementById(id).getElementsByTagName('td').item(i).className == 'name') {
    3. document.getElementById(id).getElementsByTagName('td').item(i).innerHTML = GetDepthXmlValue('campaign_name', j, '&nbsp;');
    4. }


    Der Code fügt also nacheinander die Knoten in die Tabellenstruktur ein.

    Ich möchte aber vorher keine feste Tabellenstruktur aufbauen müssen, sondern die Tabelle sozusagen sequentiell aufbauen, wenn eine Anfrage generiert wird, die den XML-File mit sagen wir 12 Data-Einträgen erstellt .. oder 18 .. oder 20 ...

    Ich glaub es ist hierbei nicht so entscheidend, dass es sich um eine XML-Quelle handelt, könnte auch MySQL sein oder etwas anderes..

    Ist das nachvollziehbar bis hier hin?

    Vielleicht ist das jetzt ganz einfach, aber mir fehlt da einfach die Praxis ...
    MfG
  • hm...
    also der AJAX Aufruf von creatorExporter.php schreibt erstmal gar nichts, sondern gibt nur bestehende Daten wieder
    Und das Problem ist, dass du nicht weißt, wieviele Einträge die XML Datei hat
    also hast du in deinem Beispiel mal die Zahl 13 genommen
    Habe ich das richtig verstanden?

    Um erstmal eine Basis zu haben würde ich die Anzahl der Einträge mit einer PHP Funktion auslesen
    Neue Einträge hinzufügen kannst du jederzeit mit AJAX.. siehe weiter unten..

    Erst nochmal weiter zu meinem Verständnis:
    Das Array campaignNames erstellst, um zu wissen wieviele Elemente es gibt
    Mit dem Zähler j kannst du also die ganzen <Data id="**"> abfragen

    Die komplette i-Schleife, die die Inhalte mit den XML Daten füllt, könntest du übrigens durch folgendes ersetzen

    Quellcode

    1. document.getElementById(id).getElementsByTagName('td').item(++i%2).innerHTML = GetDepthXmlValue('campaign_'+document.getElementById(id).getElementsByTagName('td').item(i).className, j, '&nbsp;');



    Aber wo genau werden denn eigentlich die SELECT Felder erscheinen?
    Die DIV Klassen type und name füllst du ja nur mit Werten

    Und an welchem Punkt speicherst du denn die Formulardaten? Auch per AJAX? Oder per echtem HTML Formular?
    Bei einem echten Formular werden alle Formulardaten zu einem normalen Array
    diese könntest du dann alle mit einer Foreach speichern

    Quellcode

    1. foreach($_POST as $id => $value) {
    2. //Save
    3. }


    Beim AJAX Code solltest du übrigens beidesmal req.send(null) statt req.send() verwenden. Habe irgendwo gelesen, dass manche Browser dass "null" verlangen
  • "d0nUt" schrieb:


    Die komplette i-Schleife, die die Inhalte mit den XML Daten füllt, könntest du übrigens durch folgendes ersetzen

    Quellcode

    1. document.getElementById(id).getElementsByTagName('td').item(++i%2).innerHTML = GetDepthXmlValue('campaign_'+document.getElementById(id).getElementsByTagName('td').item(i).className, j, '&nbsp;');



    Intelligente Lösung, werde ich später mal ausprobieren. Dankeschön.

    "d0nUt" schrieb:

    hm...
    also der AJAX Aufruf von creatorExporter.php schreibt erstmal gar nichts, sondern gibt nur bestehende Daten wieder
    Und das Problem ist, dass du nicht weißt, wieviele Einträge die XML Datei hat
    also hast du in deinem Beispiel mal die Zahl 13 genommen
    Habe ich das richtig verstanden?


    Absolut korrekt.

    "d0nUt" schrieb:


    Erst nochmal weiter zu meinem Verständnis:
    Das Array campaignNames erstellst, um zu wissen wieviele Elemente es gibt
    Mit dem Zähler j kannst du also die ganzen <Data id="**"> abfragen


    Genau, j repräsentiert die Daten für die Tabellenzeilen. Pro Tabellenzeile ist eine ID vergeben, die der Data ID entspricht.

    "d0nUt" schrieb:


    Aber wo genau werden denn eigentlich die SELECT Felder erscheinen?
    Die DIV Klassen type und name füllst du ja nur mit Werten



    Die Select-Felder werden in der gleichen Datei erzeugt, die (bisher) feste Tabellenstruktur erstellt wird, also vor diesem Code:

    Quellcode

    1. for($i = 1; $i <= 13; $i++) {
    2. echo "<tr id=\"D".$i."\">\n";
    3. echo " <th width=\"20\">\n";
    4. echo " <div class=\"nr\">".$i."</div>\n";
    5. echo " </th>\n";
    6. echo " <td class=\"name\">\n";
    7. echo " <div class=\"name\">--</div>\n";
    8. echo " </td>\n";
    9. echo " <td class=\"type\">\n";
    10. echo " <div class=\"type\">--</div>\n";
    11. echo " </td>\n";
    12. echo "</tr>";
    13. }
    Alles anzeigen


    "d0nUt" schrieb:


    Und an welchem Punkt speicherst du denn die Formulardaten? Auch per AJAX? Oder per echtem HTML Formular?


    Ach, ich hatte bei dem obigen Code noch was vergessen, und zwar: Die Funktion requestXML(), die den XML-File erzeugt, braucht noch eine zusaetzliche Deklaration, damit der Inhalt des Select-Feldes ueberhaupt geholt werden kann, also z.B. so:

    Quellcode

    1. function RequestXML(selectCat) {
    2. var cat = document.getElementById(selectCat).value;
    3. if (ajax) {
    4. var url = 'creatorExporter.php?source1=OverviewType&selectCat='+cat;
    5. ........


    (Das kommt davon, wenn man nich testet, was man schreibt).

    Mal eine Frage:

    Kann ich mir die Tabellenstruktur nicht direkt dynamisch in der processReqChange() aufbauen und in das Dokument schreiben?

    Die Anzahl der campaign_name Elemente repräsentiert ja die Anzahl der Datenknoten.

    Über

    Quellcode

    1. var tableCounter = response.getElementsByTagName('campaign_name');
    2. tableCounter.length;


    kann diese Anzahl in der processReqChange() geholt werden.

    Wenn ich jetzt, bevor die XML-Daten gefüllt werden, die entsprechende Tabellenstruktur direkt über processReqChange() aufbaue, sollte es doch funktionieren?

    Die Frage ist, wie ich durch die processReqChange() die Tabellenstruktur aufbaue, so dass sie ins eigentliche Dokument geschrieben wird? Ist das möglich?
  • also mit ajax an die anzahl der XML daten zu kommen um damit die php-for-schleife zu beeinflussen funktioniert nicht..

    aber du hast 2 möglichkeiten
    1) du zählst die elemente mit einer php funktion und benutzt diesen wert als abbruchbedingung für die schleife

    Quellcode

    1. $count = substr_count(file_get_contents('datei.xml'), '</Data>');


    2) du entfernst die for-schleife mit den ganzen spalten aus deiner formular datei und fügst sie in eine weitere ajax datei ein, deren inhalt du mit <body onload="loadXML()"> laden kannst

    Erstere klingt für mich effizienter ;)
    Letztere sieht vielleicht schön aus, wenn die inhalte nacheinander geladen werden (bei großen dateien sicherlich)
  • "d0nUt" schrieb:

    also mit ajax an die anzahl der XML daten zu kommen um damit die php-for-schleife zu beeinflussen funktioniert nicht..


    OK, ist einleuchtend.

    "d0nUt" schrieb:


    du entfernst die for-schleife mit den ganzen spalten aus deiner formular datei und fügst sie in eine weitere ajax datei ein, deren inhalt du mit <body onload="loadXML()"> laden kannst


    Das klingt interessant; aber ist das so wirklich realisierbar?

    Es wird ja ein Dokument geladen, wo folgendes abläuft:

    - Select-Box für die Benutzeraktion
    - Statische Tabelle mit IDs
    - Wird ein Eintrag aus dieser SelectBox gewählt, wird daraufhin die XML-Datei gemäß der Benutzereingabe generiert (durch die requestXML Funktion)
    - requestXML ruft dann die processReqChange Funktion auf, die die XML-Daten in die Tabelle füllt
    - Die Daten werden in den entsprechenden statischen Tabellenfeldern anhand der IDs eingefügt

    Um jetzt von den statischen Tabellenfeldern wegzukommen bedeutet das für mich doch, dass ich die Tabelle aufbauen muss, nachdem der Benutzer die Auswahl in der Select-Box erledigt hat und nachdem die requestXML Funktion die entsprechend zu generierende XML-Datei erzeugt hat. Zudem muss diese dynamische Tabelle aufgebaut werden, bevor processReqChange die Tabellenfelder füllt.

    Der Ablauf ist also so:

    - Auswahl durch Benutzer
    - Erzeugung der XML-Datei
    - Knoten zählen = Anzahl der Tabellenzeilen
    - Mit dieser Anzahl dynamische Tabelle generieren
    - Tabellefelder der dynamisch generierten Tabelle mit XML Daten durch processReqChange füllen.

    Mein einziges Problem ist jetzt, dass ich nicht weiss, wie man die Tabelle dynamisch generiert, geht das vielleicht komplett über AJAX? Kann ich nicht im Hauptdokument einen Table-Tag mit ID erzeugen, oder einen DIV-Tag mit ID erzeugen und diesen via Ajax mit der Anzahl an Tabellenzeilen/spalten füllen, die ich brauche?

    Wie ist das zu realisieren?

    Danke vorab
    Um Rekursionen zu verstehen, muss man zuerst Rekursionen verstehen...
  • "xound" schrieb:

    - Auswahl durch Benutzer
    - Erzeugung der XML-Datei
    - Knoten zählen = Anzahl der Tabellenzeilen
    - Mit dieser Anzahl dynamische Tabelle generieren
    - Tabellefelder der dynamisch generierten Tabelle mit XML Daten durch processReqChange füllen.


    genau so hab ich mir das vorgstellt :)
    ich habe nur das gefühl, dass du davon ausgehst, dass du mit Ajax nur "Inhalte" nachladen kannst..
    aber du kannst auch HTML Codes nachladen

    deine creatorExporter.php könnte ja die XML Datei schreiben
    und gleichzeitig die komplette html tabelle, deren Spalten du bisher mit hilfe von ajax einzeln befüllt hast, zurückgeben...

    der browser denkt dann, der code würde wirklich an dieser stelle stehen - wie bei einem php include
    du kannst also in dieser tabelle wiederum weitere ajax funktionen einbauen.. und ganz normal mit JavaScript über document.getElementById(id) & co weiterverarbeiten


    letztendlich müsste deine hauptdatei müsste also nur das select und ein leeres div erhalten (+ ajax code im head)
    bei einer select auswahl würde dann die xml datei erzeugt und die html tabelle in das div geladen

    Quellcode

    1. <html><head>/*AJAX*/</head>
    2. <body>
    3. /*deinselect*/
    4. <div id="xmlinhalt"></div>
    5. </body>
    6. </html>
  • "d0nUt" schrieb:

    "xound" schrieb:

    - Auswahl durch Benutzer
    - Erzeugung der XML-Datei
    - Knoten zählen = Anzahl der Tabellenzeilen
    - Mit dieser Anzahl dynamische Tabelle generieren
    - Tabellefelder der dynamisch generierten Tabelle mit XML Daten durch processReqChange füllen.


    genau so hab ich mir das vorgstellt :)
    ich habe nur das gefühl, dass du davon ausgehst, dass du mit Ajax nur "Inhalte" nachladen kannst..
    aber du kannst auch HTML Codes nachladen



    Jetzt ist es nachvollziehbar, ja. Ich hab mir das Beispiel mal genau angesehen und verstanden, wie man HTML-Codes nachlädt.

    Wie das denn mit dem Löschen nachgeladener HTML-Codes? Kann ich das, was per Ajax nachgeladen wurde in einem Rutsch löschen, um neue HTML-Codes nachzuladen?

    Kurz zur Erklärung: Nehmen wir an, ein Benutzer macht einen Select und bekommt 13 Zeilen Daten angezeigt. Daraufhin macht er einen neuen Select, der nur 8 Zeilen ausgibt. Die letzten 5 Zeilen vom vorherigen Select bleiben dann stehen. Kann man das irgendwie neu initialisieren, so dass die ganze Tabelle überschrieben wird?
    Um Rekursionen zu verstehen, muss man zuerst Rekursionen verstehen...