XML-Analyse einer Variablenzeichenfolge in JavaScript

203

Ich habe eine variable Zeichenfolge , die wohlgeformtes und gültiges XML enthält. Ich muss JavaScript-Code verwenden, um diesen Feed zu analysieren.

Wie kann ich dies mit (browserkompatiblem) JavaScript-Code erreichen?

David Bonnici
quelle

Antworten:

90

Update: Eine korrektere Antwort finden Sie in der Antwort von Tim Down .

Internet Explorer und beispielsweise Mozilla-basierte Browser stellen unterschiedliche Objekte für die XML-Analyse bereit. Daher ist es ratsam, ein JavaScript-Framework wie jQuery zu verwenden, um die Unterschiede zwischen den Browsern zu beheben.

Ein wirklich einfaches Beispiel ist:

var xml = "<music><album>Beethoven</album></music>";

var result = $(xml).find("album").text();

Hinweis: Wie in den Kommentaren erwähnt; jQuery führt überhaupt keine XML-Analyse durch, sondern basiert auf der DOM innerHTML-Methode und analysiert sie wie HTML, also seien Sie vorsichtig, wenn Sie HTML-Elementnamen in Ihrem XML verwenden. Aber ich denke, es funktioniert ziemlich gut für einfaches XML-Parsen, aber es wird wahrscheinlich nicht für intensives oder dynamisches XML-Parsen empfohlen, bei dem Sie nicht im Voraus wissen, welches XML herunterkommt, und dies testet, ob alles wie erwartet analysiert wird.

Schleifer Versluys
quelle
6
Der Code zum Abstrahieren des Unterschieds beim XML-Parsen zwischen IE und anderen Browsern besteht aus ein paar trivialen Zeilen. Es lohnt sich also nicht, 50 KB jQuery für sich allein zu verwenden. Das Manipulieren des DOM des resultierenden XML ist eine andere Sache.
Tim Down
7
Und etwas, das ich zum Zeitpunkt der Veröffentlichung meines vorherigen Kommentars nicht erkannt habe, ist, dass jQuery das XML nicht einmal analysiert, sondern es einfach als innerHTMLEigenschaft eines Elements zuweist , das überhaupt nicht zuverlässig ist.
Tim Down
Beachten Sie, dass JQuery keine XML-Namespaces unterstützt. Siehe zachleat.com/web/2008/05/10/selecting-xml-with-javascript
mikemaccana
10
Diese Antwort ist falsch. Siehe stackoverflow.com/questions/2124924/… , stackoverflow.com/questions/2908899/… , die Antwort von @Tim Down und die jQuery-Dokumentation selbst, in der es heißt: "Beachten Sie, dass [ jQuery()] HTML analysiert, nicht XML"
Crescent Fresh
2
@SanderVersluys: Da der Autor keine andere Antwort akzeptiert, würde ich Ihrer Antwort einen Hinweis hinzufügen, der auf die richtige Antwort von @ TimDown verweist . Auf diese Weise müssen die Leute nicht alle diese Kommentare lesen, um die richtige Antwort zu finden.
Sinnvoll
321

Aktualisierte Antwort für 2017

Im Folgenden wird eine XML-Zeichenfolge in allen gängigen Browsern in ein XML-Dokument analysiert. Sofern Sie keine Unterstützung für IE <= 8 oder einen unbekannten Browser benötigen, können Sie die folgende Funktion verwenden:

function parseXml(xmlStr) {
   return new window.DOMParser().parseFromString(xmlStr, "text/xml");
}

Wenn Sie IE <= 8 unterstützen müssen, wird Folgendes ausgeführt:

var parseXml;

if (typeof window.DOMParser != "undefined") {
    parseXml = function(xmlStr) {
        return new window.DOMParser().parseFromString(xmlStr, "text/xml");
    };
} else if (typeof window.ActiveXObject != "undefined" &&
       new window.ActiveXObject("Microsoft.XMLDOM")) {
    parseXml = function(xmlStr) {
        var xmlDoc = new window.ActiveXObject("Microsoft.XMLDOM");
        xmlDoc.async = "false";
        xmlDoc.loadXML(xmlStr);
        return xmlDoc;
    };
} else {
    throw new Error("No XML parser found");
}

Sobald Sie eine Documenterhalten haben parseXml, können Sie die üblichen DOM-Durchlaufmethoden / -eigenschaften wie childNodesund verwenden getElementsByTagName(), um die gewünschten Knoten abzurufen.

Anwendungsbeispiel:

var xml = parseXml("<foo>Stuff</foo>");
alert(xml.documentElement.nodeName);

Wenn Sie jQuery verwenden, können Sie ab Version 1.5 die integrierte parseXML()Methode verwenden, die funktional mit der obigen Funktion identisch ist.

var xml = $.parseXML("<foo>Stuff</foo>");
alert(xml.documentElement.nodeName);
Tim Down
quelle
56
Ich stimme zu, dies sollte als Antwort akzeptiert werden. Meine Antwort ist von Anfang an so alt, dass ich es immer merkwürdig finde, dass es immer noch positive Stimmen gibt. Möchte jemand meine akzeptierte Antwort entfernen? Und ist das Abstimmungssystem fehlerhaft? Upvote dieses Volk!
Sander Versluys
@SanderVersluys: Können Sie Ihre Antwort entfernen?
Witman
1
Ich musste Sie dafür herabstimmen, dass es keine anderen anständigen Antworten gibt. @ SandersVersluys Antwort hat in meinem Fall gut funktioniert. Was daran nicht anständig ist, weiß ich nicht.
Eric
2
@ EricTurner: Ich stehe dazu und Sander selbst hat seine Antwort abgelehnt. In jQuery-Dokumenten wird empfohlen, das $()XML-Parsing nicht zu verwenden . Lesen Sie die Kommentare genauer durch: Es funktioniert in vielen Situationen einfach nicht.
Tim Down
1
@ DWoldrich: Ich habe es im Web in beide Richtungen gesehen und ich vermute, dass es in beide Richtungen funktioniert. Diejenige , die einer maßgeblichen Antwort am nächsten kommt , ist msdn.microsoft.com/en-us/library/ms761398(v=vs.85).aspx , die besagt, dass ein Boolescher Wert verwendet werden sollte. Wie viel Wert Sie darauf legen, liegt jedoch ganz bei Ihnen. Die parseXML()Methode von jQuery verwendet eine Zeichenfolge. Ich bin etwas vorsichtig, die Antwort zu ändern, da ich momentan keine einfache Möglichkeit habe, sie zu testen.
Tim Down
19

Die meisten Beispiele im Web (und einige der oben dargestellten) zeigen, wie ein XML aus einer Datei auf browserkompatible Weise geladen wird . Dies erweist sich als einfach, außer im Fall von Google Chrome, das die document.implementation.createDocument()Methode nicht unterstützt . Wenn Sie Chrome verwenden, müssen Sie zum Laden einer XML-Datei in ein XmlDocument-Objekt das integrierte XmlHttp-Objekt verwenden und die Datei dann laden, indem Sie den URI übergeben.

In Ihrem Fall ist das Szenario anders, da Sie das XML aus einer Zeichenfolgenvariablen und nicht aus einer URL laden möchten . Für diese Anforderung funktioniert Chrome jedoch angeblich genau wie Mozilla (oder wie ich gehört habe) und unterstützt die parseFromString () -Methode.

Hier ist eine Funktion, die ich verwende (sie ist Teil der Browserkompatibilitätsbibliothek, die ich gerade erst baue):

function LoadXMLString(xmlString)
{
  // ObjectExists checks if the passed parameter is not null.
  // isString (as the name suggests) checks if the type is a valid string.
  if (ObjectExists(xmlString) && isString(xmlString))
  {
    var xDoc;
    // The GetBrowserType function returns a 2-letter code representing
    // ...the type of browser.
    var bType = GetBrowserType();

    switch(bType)
    {
      case "ie":
        // This actually calls into a function that returns a DOMDocument 
        // on the basis of the MSXML version installed.
        // Simplified here for illustration.
        xDoc = new ActiveXObject("MSXML2.DOMDocument")
        xDoc.async = false;
        xDoc.loadXML(xmlString);
        break;
      default:
        var dp = new DOMParser();
        xDoc = dp.parseFromString(xmlString, "text/xml");
        break;
    }
    return xDoc;
  }
  else
    return null;
}
Cerebrus
quelle
16
Ich bin mir der kontroversen Meinungen zum Browser-Sniffing bewusst und aus diesem Grund habe ich diese Funktion hier nicht aufgenommen. Es wurde jedoch nicht festgestellt, dass es FALSCH ist. In jedem Fall ist dies ein anschauliches Beispiel.
Cerebrus
1
Ich glaube, es ist falsch, dass man nicht garantieren kann, dass es richtig ist. Jeder kann die UA-Zeichenfolgen fälschen, und es ist zweifelhaft, dass JEDER Nicht-IE-Browser DOMParser unterstützt und dass Ihr Browser-Sniffing PERFEKT ist. Und außerdem ist es viel einfacher, es richtig zu machen:if(window.ActiveXObject){...}
1j01
Jetzt unterstützt IE9 + DOMParser . Wie werden Sie das unterstützen? -1 für das, was @ 1j01 sagt. Alles was Sie überprüfen müssen, ist var dp; try{ dp = new DOMParser() } catch(e) { }; if(dp) { // DOMParser supported } else { // alert('you need to consider upgrading your browser\nOr pay extra money so developer can support the old versions using browser sniffing (eww)') }.
Annie
13

Marknote ist ein netter, leichter, browserübergreifender JavaScript-XML-Parser. Es ist objektorientiert und enthält viele Beispiele. Außerdem ist die API dokumentiert. Es ist ziemlich neu, aber es hat bisher in einem meiner Projekte gut funktioniert. Eine Sache, die ich daran mag, ist, dass es XML direkt aus Zeichenfolgen oder URLs liest und Sie es auch verwenden können, um das XML in JSON zu konvertieren.

Hier ist ein Beispiel dafür, was Sie mit Marknote tun können:

var str = '<books>' +
          '  <book title="A Tale of Two Cities"/>' +
          '  <book title="1984"/>' +
          '</books>';

var parser = new marknote.Parser();
var doc = parser.parse(str);

var bookEls = doc.getRootElement().getChildElements();

for (var i=0; i<bookEls.length; i++) {
    var bookEl = bookEls[i];
    // alerts "Element name is 'book' and book title is '...'"
    alert("Element name is '" + bookEl.getName() + 
        "' and book title is '" + 
        bookEl.getAttributeValue("title") + "'"
    );
}
Mike McMillien
quelle
Es scheint, dass marknote einen reinen Javascript-Parser implementiert. Es bedeutet, dass es mit jeder Javascript-Engine kompatibel sein sollte, wo immer es in einem Browser, in node.js oder in einer eigenständigen Javascript-Engine verwendet wird ...
Coyote
8

Ich habe immer den folgenden Ansatz verwendet, der in IE und Firefox funktioniert.

Beispiel XML:

<fruits>
  <fruit name="Apple" colour="Green" />
  <fruit name="Banana" colour="Yellow" />
</fruits>

JavaScript:

function getFruits(xml) {
  var fruits = xml.getElementsByTagName("fruits")[0];
  if (fruits) {
    var fruitsNodes = fruits.childNodes;
    if (fruitsNodes) {
      for (var i = 0; i < fruitsNodes.length; i++) {
        var name = fruitsNodes[i].getAttribute("name");
        var colour = fruitsNodes[i].getAttribute("colour");
        alert("Fruit " + name + " is coloured " + colour);
      }
    }
  }
}
John Topley
quelle
Wie würden Sie einen Wert annehmen, wenn Sie diese Situation <Frucht> Wert </ Frucht> hätten?
Siblja
1
@Siblja müssen Sie innerTextanstelle vongetAttribute()
Manux22
8

Anscheinend bietet jQuery ab Version 1.5 jetzt jQuery.parseXML http://api.jquery.com/jQuery.parseXML/

jQuery.parseXML( data ) Kehrt zurück: XMLDocument

Jamie Pate
quelle
2

Bitte werfen Sie einen Blick auf XML DOM Parser ( W3Schools ). Es ist ein Tutorial zum Parsen von XML-DOMs. Der tatsächliche DOM-Parser unterscheidet sich von Browser zu Browser, aber die DOM-API ist standardisiert und bleibt gleich (mehr oder weniger).

Verwenden Sie alternativ E4X, wenn Sie sich auf Firefox beschränken können. Es ist relativ einfach zu bedienen und seit Version 1.6 Teil von JavaScript. Hier ist ein kleines Beispiel für die Verwendung ...

//Using E4X
var xmlDoc=new XML();
xmlDoc.load("note.xml");
document.write(xmlDoc.body); //Note: 'body' is actually a tag in note.xml,
//but it can be accessed as if it were a regular property of xmlDoc.
Autodidakt
quelle
0
<script language="JavaScript">
function importXML()
{
    if (document.implementation && document.implementation.createDocument)
    {
            xmlDoc = document.implementation.createDocument("", "", null);
            xmlDoc.onload = createTable;
    }
    else if (window.ActiveXObject)
    {
            xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
            xmlDoc.onreadystatechange = function () {
                    if (xmlDoc.readyState == 4) createTable()
            };
    }
    else
    {
            alert('Your browser can\'t handle this script');
            return;
    }
    xmlDoc.load("emperors.xml");
}

function createTable()
{
    var theData="";
    var x = xmlDoc.getElementsByTagName('emperor');
    var newEl = document.createElement('TABLE');
    newEl.setAttribute('cellPadding',3);
    newEl.setAttribute('cellSpacing',0);
    newEl.setAttribute('border',1);
    var tmp = document.createElement('TBODY');
    newEl.appendChild(tmp);
    var row = document.createElement('TR');
    for (j=0;j<x[0].childNodes.length;j++)
    {
            if (x[0].childNodes[j].nodeType != 1) continue;
            var container = document.createElement('TH');
            theData = document.createTextNode(x[0].childNodes[j].nodeName);
            container.appendChild(theData);
            row.appendChild(container);
    }
    tmp.appendChild(row);
    for (i=0;i<x.length;i++)
    {
            var row = document.createElement('TR');
            for (j=0;j<x[i].childNodes.length;j++)
            {
                    if (x[i].childNodes[j].nodeType != 1) continue;
                    var container = document.createElement('TD');
                    var theData = document.createTextNode(x[i].childNodes[j].firstChild.nodeValue);
                    container.appendChild(theData);
                    row.appendChild(container);
            }
            tmp.appendChild(row);
    }
    document.getElementById('writeroot').appendChild(newEl);
}
</script>
</HEAD>

<BODY onLoad="javascript:importXML();">
<p id=writeroot> </p>
</BODY>

Weitere Informationen finden Sie unter http://www.easycodingclub.com/xml-parser-in-javascript/javascript-tutorials/

easycodingclub
quelle
0

Haftungsausschluss : Ich habe einen Fast-XML-Parser erstellt

Ich habe einen Fast-XML-Parser erstellt , um eine XML-Zeichenfolge zu analysieren in ein JS / JSON-Objekt oder ein Zwischen-Traversal-Objekt . Es wird erwartet, dass es in allen Browsern kompatibel ist (jedoch nur in Chrome, Firefox und IE getestet).

Verwendung

var options = { //default
    attrPrefix : "@_",
    attrNodeName: false,
    textNodeName : "#text",
    ignoreNonTextNodeAttr : true,
    ignoreTextNodeAttr : true,
    ignoreNameSpace : true,
    ignoreRootElement : false,
    textNodeConversion : true,
    textAttrConversion : false,
    arrayMode : false
};

if(parser.validate(xmlData)){//optional
    var jsonObj = parser.parse(xmlData, options);
}

//Intermediate obj
var tObj = parser.getTraversalObj(xmlData,options);
:
var jsonObj = parser.convertToJson(tObj);

Hinweis : Es wird kein DOM-Parser verwendet, sondern die Zeichenfolge mit RE analysiert und in ein JS / JSON-Objekt konvertiert.

Probieren Sie es online aus , CDN

Amit Kumar Gupta
quelle
-1

Sie können auch über die jquery-Funktion ($. ParseXML) die XML-Zeichenfolge bearbeiten

Beispiel Javascript:

var xmlString = '<languages><language name="c"></language><language name="php"></language></languages>';
var xmlDoc = $.parseXML(xmlString);
$(xmlDoc).find('name').each(function(){
    console.log('name:'+$(this).attr('name'))
})
user6016338
quelle