Max: mit JS Daten aus einer XML-Datei direkt ansprechen

Hallo zusammen,

ich sitze gerade vor der Aufgabe, mithilfe von Javascript Daten aus einer XML-Datei auf einer Website darzustellen.
Eigentlich gar nicht so schwer. Allerdings möchte ich einzelne Daten direkt ansprechen. Normalerweise würde ich jedem Datum ein eigenen TagName zuweisen und dann mit "getElementByTagName" drauf zugreifen.
Da nicht klar ist, welche Daten in die XML-Datei geladen werden, sind alle TagNames gleich:

  
<?xml version="1.0" encoding="UTF-8"?>  
  
<buchliste>  
        <buch id="Thiller">  
            <wert id="1" name="buch1">Illuminati</wert>  
            <wert id="2">Rosamunde Pilcher</wert>  
            <wert/>  
        </buch>  
        <buch id="Fantasy">  
            <wert id="1">die sieben Zwerge</wert>  
            <wert id="2">Frau Holle</wert>  
        </buch>  
</buchliste>  

jetzt die Frage an euch: kann ich irgendwie auf die id oder einen definierten namen zugreifen? und wenn ja wie?
Ich würde gern "Rosamunde Pilcher" nur ausgegeben haben.

vielen Dank für die Hilfe

  1. jetzt die Frage an euch: kann ich irgendwie auf die id oder einen definierten namen zugreifen? und wenn ja wie?

    Mit SelectNodes bzw. evaluate sollte das funktionieren.
    Einfacher sicherlich mit JQuery.

    1. Hallo,

      Einfacher sicherlich mit JQuery.

      Das kann natürlich sein. Ich bin dabei mich da rein zu arbeiten, allerdings stehe ich nun vor dem Problem, dass er mir wenn ich mit

        
      function Ausgeben() {  
          $.get("media.xml", function(Array){  
              $(Array).find("wert").each(function(){  
                  var $myMedia = $(this);  
                  var id2 = $myMedia.attr("id");  
                  $("#mediaContainer").append(id2);  
              })  
          })  
         };  
      
      

      alle id ausgeben möchte, er alle ids im Array an der Stelle [0] speichert.
      Als Ausgabe kommt dann: 1212

      Ich würde die Ids jeweils an eine eigene Stelle des Arrays speichern.
      Habt ihr da eine Idee?

      Gruß Max

      1. er alle ids im Array an der Stelle [0] speichert.

        Das verstehe ich nicht, was meinst du?

        Als Ausgabe kommt dann: 1212

        Das ist doch richtig.

        Ich würde die Ids jeweils an eine eigene Stelle des Arrays speichern.

        Ich sehe bei dir kein Array?!

        1. Das ist doch richtig.

          Ich sehe bei dir kein Array?!

          Ja, du hast recht. Ich durchdringe das ganze erst allmählich...

          eachFunktion wird durchlaufen und gibt am Ende die Variable aus.
          In diesem Fall "1".
          anschließend durchläuft er es noch einmal mit dem nächsten Knoten "wert" und gibt wieder die Variable aus. Das macht er so lange, bis keine Knoten "wert" mehr vorhanden sind.

          Ich möchte, wenn er das einmal durchlaufen hat und die erste id hat, er das ganze in ein globales Array speichert.
          Mittel der Wahl wäre doch:

            
          arr[i] = id2;  
          i = i+1;  
          
          

          Wenn ich jetzt mit von einer anderen Funktion aus auf arr[i] zugreife, ist es allerdings leer.
          Wie kommt das?
          ich habe arr[] und i global deklariert:

            
          var i=0;  
          var arr=[];  
          
          
          1. ich habe arr[] und i global deklariert:

            Das ist schon mal nicht gut, globale Variablen sollte (und kann) man immer vermeiden.

            Wenn ich jetzt mit von einer anderen Funktion aus auf arr[i] zugreife, ist es allerdings leer.
            Wie kommt das?

            Der Request ist ja asynchron. Ich vermute mal, du greifst auf das Array zu, wenn noch keine Antwort da ist.
            Du musst das alles in der callback-Funktion(die, welche du an get übergibst) machen.

            1. Der Request ist ja asynchron. Ich vermute mal, du greifst auf das Array zu, wenn noch keine Antwort da ist.

              Das ist ein guter Hinweis. Danke!

              Du musst das alles in der callback-Funktion(die, welche du an get übergibst) machen.

              Wie sieht das denn aus, wenn eine Funktion "IdVerarbeiten" erst ausgeführt werden darf, wenn die Funktion "Ausgeben" komplett durchgelaufen ist? Was meinst du damit "welche du an get übergibst"?

                
              function IdVerarbeiten() {  
                          var g = Ausgeben();  
                          g= g+5;  
                          $("#content").append("Das Ergebnis lautet: " +g);  
                      }  
              
              

              viele Grüße

              1. Irgendwie so:

                  
                function Ausgeben() {  
                    $.get("media.xml", function(Array){  
                        $(Array).find("wert").each(function(){  
                            var $myMedia = $(this);  
                            var id2 = $myMedia.attr("id");  
                            $("#mediaContainer").append(id2);  
                        })  
                        IdVerarbeiten();  
                    })  
                   };  
                
                

                Wobei du in IdVerarbeiten nicht erst den Request absenden darfst(Ausgeben aufrufen), sondern auf die Ergebnisse des Requests zugreifen musst.
                Außerdem kann deine Funktion Ausgeben keinen vernünftigen Returnwert zurückgeben, da der Request ja noch läuft, wenn der Returnwert geliefert wird.

                1. Irgendwie so:

                  function Ausgeben() {
                      $.get("media.xml", function(Array){
                          $(Array).find("wert").each(function(){
                              var $myMedia = $(this);
                              var id2 = $myMedia.attr("id");
                              $("#mediaContainer").append(id2);
                          })
                          IdVerarbeiten();
                      })
                     };

                  
                  >   
                  > Wobei du in IdVerarbeiten nicht erst den Request absenden darfst(Ausgeben aufrufen), sondern auf die Ergebnisse des Requests zugreifen musst.  
                  > Außerdem kann deine Funktion Ausgeben keinen vernünftigen Returnwert zurückgeben, da der Request ja noch läuft, wenn der Returnwert geliefert wird.  
                    
                    
                  Danke danke danke danke! Jetzt hab ich das endlich verstanden und es funktioniert super!  
                    
                  Dieses Forum ist echt stark!  
                  
                  
      2. Wobei mir gerade noch einfällt, wenn du einfach alle wert-Elemente suchen willst, dann kannst du natürlich auch getElementsByTagName verwenden.

  2. Hallo,

    Allerdings möchte ich einzelne Daten direkt ansprechen. Normalerweise würde ich jedem Datum ein eigenen TagName zuweisen und dann mit "getElementByTagName" drauf zugreifen.

    Und was spricht dagegen?

    Für XML-Dokumente kannst du in JavaScript grundsätzlich dieselben Methoden verwenden wie für HTML-Dokumente: getElementById, getElementsByTagName / getElementsByTagNameNS, querySelector / querySelectorAll.

    getElementsByTagName(NS) und querySelector(All) sind sowohl am Dokument als auch an einzelnen Dokumentknoten verfügbar.

    <buchliste>
            <buch id="Thiller">
                <wert id="1" name="buch1">Illuminati</wert>
                <wert id="2">Rosamunde Pilcher</wert>
                <wert/>
            </buch>
            <buch id="Fantasy">
                <wert id="1">die sieben Zwerge</wert>
                <wert id="2">Frau Holle</wert>
            </buch>
    </buchliste>

      
    Das ist eine seltsame XML-Struktur. Ein Genre sollte nicht »buch« heißen und ein Buch nicht »wert«. Außerdem sollten IDs dokumentweit eindeutig sein, sonst sind sie keine IDs.  
      
    
    > jetzt die Frage an euch: kann ich irgendwie auf die id oder einen definierten namen zugreifen?  
      
    Da bietet sich getElementById an, ansonsten querySelector(All) für komplexere Queries.  
      
    Mathias
    
    -- 
    [9elements – Ruby on Rails and HTML5 development](http://9elements.com/)
    
    1. Hallo Mathias

      Das ist eine seltsame XML-Struktur. Ein Genre sollte nicht »buch« heißen und ein Buch nicht »wert«. Außerdem sollten IDs dokumentweit eindeutig sein, sonst sind sie keine IDs.

      ja die Struktur ist etwas seltsam, ist auch nur ein Beispiel.

      Da bietet sich getElementById an, ansonsten querySelector(All) für komplexere Queries.

      wie sähe das in html aus?
      ich habe folgende Struktur:

        
      <html>  
      <head>  
          <title>Page Title</title>  
        
          <script type="application/x-javascript">  
              if(window.XMLHttpRequest)  
              {  
              xhttp=new XMLHttpRequest();  
              }  
              else /  
              {  
              xhttp=new ActiveXObject("Microsoft.XMLHTTP");  
              }  
              xhttp.open("GET","buecher",false);  
              xhttp.send("");  
              xmlDoc=xhttp.responseXML;  
        
        
              var x = xmlDoc.getElementById(2).nodeValue;  
        
              document.writeln(x);  
        
        
          </script>  
      </head>  
      <body>  
        
      </body>  
      </html>  
      
      

      Gruß
      Max

      1. Hallo,

        var x = xmlDoc.getElementById(2).nodeValue;

        Völlig richtig soweit – aber ein Elementknoten hat keinen nodeValue, höchstens einen tagName.

        Falls du den Textinhalt brauchst, so kannst du

        • den ersten Textknoten darin ansprechen, z.B. über element.firstChild.nodeValue
        • manche Browser kennen die Eigenschaft textContent (Firefox, Webkit/Blink), andere innerText (IE)
        var element = xmlDoc.getElementById("2");  
        var textContent = element.textContent || element.innerText;
        

        Solange es nur einen Textknoten gibt, reicht natürlich .firstChild.nodeValue.

        Mathias

      2. Da bietet sich getElementById an, ansonsten querySelector(All) für komplexere Queries.

        wie sähe das in html aus?
        ich habe folgende Struktur:

        getElementById kannst du aber nur nutzen, wenn du das Attribut id auch als id-Typ definierst und auch verwendest.
        Das ist bei dir ja nicht der Fall. Welches Element soll der in deinem Fall denn finden?
        <wert id="2">Rosamunde Pilcher</wert> oder <wert id="2">Frau Holle</wert>
        Außerdem dürfen IDs dann auch nicht mit einer Ziffer beginnen.
        Wie gesagt, am einfachsten kommst du sicher mit jQuery ans Ziel, wobei ich Bedenken hätte, ein XML-Element mit CSS Selektoren zu bestimmen. Das funktioniert zwar, ist aber nicht gtanz sauber. Dafür ist eigentlich XPath vorgesehen.

        1. Hi!

          getElementById kannst du aber nur nutzen, wenn du das Attribut id auch als id-Typ definierst und auch verwendest.
          Das ist bei dir ja nicht der Fall.

          Um den Attributtyp zu kennen, müsste der Browser die DTD oder sonst eine Grammatik lesen. Das tut er nicht, die Browser setzen in diesem Fall einen nicht-validierender XML-Parser ein, der eine eventuell angegebene DTD ignoriert.

          Außerdem halten sich die neueren Browser an die Definition von getElementById und IDs aus DOM4. Das gilt auch für XML-Dokumente:
          http://dom.spec.whatwg.org/#concept-id
          http://dom.spec.whatwg.org/#dom-document-getelementbyid
          DOM4 macht es sich da ganz einfach. Eine ID bekommt ein Element durch ein Attribut namens »id«. Grammatiken und Namensräume sind außen vor.

          (Übrigens gäbe es ja noch xml:id, aber das setzt kein Browser um, soweit ich weiß, und DOM Core hat auch nie darauf aufgebaut.)

          Wie gesagt, am einfachsten kommst du sicher mit jQuery ans Ziel, wobei ich Bedenken hätte, ein XML-Element mit CSS Selektoren zu bestimmen. Das funktioniert zwar, ist aber nicht gtanz sauber.

          Wieso? CSS-Selektoren sind genauso wie XPath nur eine Sprache, die zum Auswählen von Elementen/Knoten erfunden wurde. Beide sind auf XML-Dokumente anwendbar. Für die Interpretation beider hat der Browser native JavaScript-Methoden. CSS-Selektoren sind i.d.R. einfacher als XPath. CSS-Selektoren kommen dank jQuery und querySelector(All) überall im Frontend vor, XPath höchstens bei meist serverseitigen XSL-Transformationen.

          Grüße,
          Mathias

          1. Um den Attributtyp zu kennen, müsste der Browser die DTD oder sonst eine Grammatik lesen. Das tut er nicht, die Browser setzen in diesem Fall einen nicht-validierender XML-Parser ein, der eine eventuell angegebene DTD ignoriert.

            Ja, das ist so. Deswegen sucht getElementById auch nur ein Element mit dem Attribut namens »id«, die Prüfung auf Eindeutigkeit findet ja beim validieren statt. Die Browser können gar nicht anders.
            Das ändert aber nichts an der Tatsache, daß das Attribut id nicht eindeutig sein muss.

            In diesem Fall ist es nicht eindeutig und das ist erst mal kein Fehler.

            Wieso? CSS-Selektoren sind genauso wie XPath nur eine Sprache, die zum Auswählen von Elementen/Knoten erfunden wurde.

            CSS ist dazu da das Aussehen von Dokumenten zu definieren. XML ist erst mal nur ein Datenformat und beschreibt in den seltensten Fällen ein Dokument.
            XPath dagegen ist dazu gedacht einen beliebigen Teil der beschriebenen Daten in einer XML-Struktur zu selektieren.
            Das man um das Aussehen zu bestimmen auch einzelne Elemente selektieren muss, und daher CSS-Selektoren auch auf XML anwenden kann ist schon richtig, ich finde es aber ungewöhnlich.

            Beide sind auf XML-Dokumente anwendbar. Für die Interpretation beider hat der Browser native JavaScript-Methoden.

            Aber außerhalb von Browsern wirst du keine Anwendung finden, die über CSS-Selektoren geht.

            CSS-Selektoren kommen dank jQuery und querySelector(All) überall im Frontend vor, XPath höchstens bei meist serverseitigen XSL-Transformationen.

            Eher anders herum, nur im Browser hat man das überhaupt zur Verfügung, an vielen anderen Stellen hat man XPath.

            1. Hallo,

              CSS ist dazu da das Aussehen von Dokumenten zu definieren.
              XPath dagegen ist dazu gedacht einen beliebigen Teil der beschriebenen Daten in einer XML-Struktur zu selektieren.

              Dafür sind auch CSS-Selektoren gedacht. o_O

              Historisch gesehen haben CSS-Selektoren einen anderen Hintergrund, klar. Technisch gesehen macht das jedoch keinen Unterschied. jQuery und andere Programme haben CSS-Selektoren ihrem historischen Kontext entnommen – und sie haben sich als allgemeine Abfragesprache als nützlich erwiesen.

              Aber außerhalb von Browsern wirst du keine Anwendung finden, die über CSS-Selektoren geht.

              Das stimmt so nicht. Nokogiri beispielsweise unterstützt sie. Acceptance-Tests in Cucumber/Capybara oder Selenium arbeiten ebenfalls mit CSS-Selektoren. Und das ist nur das Ruby-Ökosystem, in dem ich mich ein wenig auskenne. In Node.js ist es m.W. auch kein Problem, jQuery zu laden und es auf sämtliche DOMs anzuwenden.

              Mathias

              1. und sie haben sich als allgemeine Abfragesprache als nützlich erwiesen.

                Nützlich sicher, XPath wäre genau so nützlich gewesen und würde mir besser gefallen.

                Ich glaube wir kommen da nicht überein.
                JS-Entwickler kennen vielleicht eher CSS als XPath.
                Ich würde ehrlicherweise in JS auch jQuery nehmen, weil es einfach einfacher ist und mich damit herrausreden, daß das jQuery-Selektoren sind.

                Aber außerhalb von Browsern wirst du keine Anwendung finden, die über CSS-Selektoren geht.

                Das stimmt so nicht. Nokogiri beispielsweise unterstützt sie. Acceptance-Tests in Cucumber/Capybara oder Selenium arbeiten ebenfalls mit CSS-Selektoren. Und das ist nur das Ruby-Ökosystem, in dem ich mich ein wenig auskenne. In Node.js ist es m.W. auch kein Problem, jQuery zu laden und es auf sämtliche DOMs anzuwenden.

                OK, also außerhalb der Web-Entwicklung.

                Und wehe du findest jetzt wieder eine lib, die CSS-Selektoren anbietet! ;)

  3. Hallo Max,

    ich sitze gerade vor der Aufgabe, mithilfe von Javascript Daten aus einer XML-Datei auf einer Website darzustellen.

    Die zielführenden Hinweise hat ja Mathias schon gegeben.

    Falls das Projekt zum einen JavaScript voraussetzen darf und zum anderen XSLT kein Hindernis darstellt, wäre vielleicht mal ein Blick auf das noch wenig bekannte Konzept von Saxon-CE (XSLT 2.0 im Browser) interessant. Es eignet sich insbesondere für XML-datengetriebene Anwendungen im Bereich Online-Dokumentation & Co., siehe die CE-Doku selbst.

    Dieses damit umgesetzte Testbeispiel demonstriert die wesentlichen Techniken mit HTML-Tabelle und SVG-Kreisdiagramm sowie Interaktion im Formularkontext (ixsl:onclick).

    Grüße,
    Thomas