JavaScript'te bir değişken dizenin XML ayrıştırma


205

Ben iyi biçimli ve geçerli XML içeren değişken bir dize var. Bu feed'i ayrıştırmak için JavaScript kodu kullanmam gerekiyor.

Bunu (tarayıcı uyumlu) JavaScript kodunu kullanarak nasıl yapabilirim?

Yanıtlar:


91

Güncelleme: Daha doğru bir cevap için Tim Down'ın cevabına bakınız .

Internet Explorer ve örneğin Mozilla tabanlı tarayıcılar, XML ayrıştırma için farklı nesneleri ortaya koyar, bu nedenle çapraz tarayıcı farklılıklarını ele almak için jQuery gibi bir JavaScript çerçevesi kullanmak akıllıca olur .

Gerçekten temel bir örnek:

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

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

Not: Yorumlarda belirtildiği gibi; jQuery gerçekten herhangi bir XML ayrıştırma yapmaz, DOM innerHTML yöntemine dayanır ve herhangi bir HTML gibi ayrıştırır, bu nedenle XML'nizde HTML öğesi adları kullanırken dikkatli olun. Ancak basit XML 'ayrıştırma' için oldukça iyi çalıştığını düşünüyorum, ancak muhtemelen hangi XML'in aşağı çıkacağını ve her şeyin beklendiği gibi ayrışması durumunda bu testleri önermediğiniz yoğun veya 'dinamik' XML ayrıştırma için önerilmez.


6
IE ve diğer tarayıcılar arasındaki XML ayrıştırma farkını soyutlama kodu birkaç önemsiz satırdır, bu nedenle kendi başına 50K jQuery'de cıvatalamaya değmez. Ortaya çıkan XML'nin DOM'sini değiştirmek başka bir konudur.
Tim Down

7
Ve önceki yorumumu gönderirken fark etmediğim bir şey, jQuery'nin XML'yi ayrıştırmaması, sadece innerHTMLgüvenilir olmayan bir öğenin özelliği olarak atamasıdır.
Tim Down

JQuery XML ad alanlarını desteklemez. Bkz. Zachleat.com/web/2008/05/10/selecting-xml-with-javascript
mikemaccana

10
Bu cevap yanlış. Bkz. Stackoverflow.com/questions/2124924/… , stackoverflow.com/questions/2908899/… , @Tim Down'un yanıtı ve jQuery belgelerinin kendisi : "[ jQuery()] XML değil , HTML'yi ayrıştırır "
Crescent Fresh

2
@SanderVersluys: yazar başka bir yanıtı kabul etmediğinden, cevabınıza @ TimDown'ın doğru cevabına bağlantı veren bir not ekleyeceğim . Bu şekilde insanlar doğru cevabı bulmak için tüm bu yorumları okumak zorunda kalmazlar.
12'de

321

2017 için güncellenmiş cevap

Aşağıda bir XML dizesi, tüm büyük tarayıcılarda bir XML belgesine ayrıştırılacaktır. IE <= 8 veya bazı belirsiz tarayıcılar için desteğe ihtiyacınız yoksa, aşağıdaki işlevi kullanabilirsiniz:

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

IE <= 8'i desteklemeniz gerekiyorsa, aşağıdakiler işi yapar:

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");
}

Bir kere Documentyoluyla elde edilen parseXml, bu tür her zamanki gibi DOM kastetmek yöntemleri / özelliklerini kullanabilirsiniz childNodesvegetElementsByTagName() istediğiniz düğümleri almak için kullanabilirsiniz.

Örnek kullanım:

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

JQuery kullanıyorsanız, sürüm 1.5'ten itibaren parseXML()yukarıdaki işlevle işlevsel olarak aynı olan yerleşik yöntemini kullanabilirsiniz .

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

56
Katılıyorum, bu cevap kabul edilmelidir. Cevabım ilk günlerden çok eskidir, her zaman hala vekillerin alındığını merak ediyorum. Kabul ettiğim cevabı kaldırmak isteyen var mı? Oylama sistemi hatalı mı? Bu insanları oylayın!
Sander

@SanderVersluys: Cevabınızı kaldırabiliyor musunuz?
Witman

1
'Başka iyi cevaplar' olmadığını söylediğin için seni küçümsemek zorunda kaldım. @SanderVersluys cevap benim durumumda iyi çalıştı. Bu konuda neyin iyi olmadığını bilmiyorum.
eric

2
@EricTurner: Ben onun yanındayım ve Sander'in kendisi cevabını reddetti. jQuery belgeleri $(), XML ayrıştırması için kullanmamanızı söyler . Yorumları daha dikkatli okuyun: pek çok durumda işe yaramaz.
Tim Down

1
@DWoldrich: Web'de her iki şekilde de gördüm ve her iki şekilde de çalıştığından şüpheleniyorum. Yetkili bir yanıta bulabildiğim en yakın şey, bir Boole kullanılması gerektiğini söyleyen msdn.microsoft.com/en-us/library/ms761398(v=vs.85).aspx . Bununla birlikte, ve bu değer ne kadar tamamen size kalmış, jQuery parseXML()yöntemi bir dize kullanır. Cevabı değiştirmeye biraz dikkat ediyorum çünkü şu anda test etmenin kolay bir yolu yok.
Tim Down

19

Çoğu web üzerinde örnekler (ve bazı yukarıda sunulan) bir XML yüklemek göstermek bir dosyadan bir tarayıcı uyumlu bir şekilde. document.implementation.createDocument()Yöntemi desteklemeyen Google Chrome haricinde bu kolaylık sağlar . Chrome kullanırken, bir XmlDocument nesnesine bir XML dosyası yüklemek için, dahili XmlHttp nesnesini kullanmanız ve ardından dosyayı URI'sini geçirerek yüklemeniz gerekir.

Sizin durumunuzda, senaryo farklıdır, çünkü XML'i bir URL'den değil , bir dize değişkeninden yüklemek istiyorsunuz . Ancak bu gereksinim için Chrome'un Mozilla gibi çalıştığı (veya duyduğum gibi) ve parseFromString () yöntemini desteklediği varsayılıyor.

İşte kullandığım bir işlev (şu anda oluşturduğum Tarayıcı uyumluluk kütüphanesinin bir parçası):

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;
}

16
Tarayıcı koklamasıyla ilgili tartışmalı fikirlerin farkındayım ve bu işlevi buraya eklemememin nedeni de bu. Ancak YANLIŞ olduğu tespit edilmemiştir. Her durumda, bu düşündürücü bir örnektir.
Cerebrus

1
Doğru olduğunu garanti edememenizin yanlış olduğuna inanıyorum. Herkes UA dizelerini taklit edebilir ve IE olmayan her tarayıcının DOMParser'ı desteklediğinden ve tarayıcı koklamanın MÜKEMMEL olduğundan şüphelidir. Ayrıca, doğru şekilde yapmak çok daha kolay:if(window.ActiveXObject){...}
1j01

IE9 + artık DOMParser'ı destekliyor , bunu nasıl destekleyeceksiniz? @ 1j01'in söylediği şey için -1. Tek yapmanız gereken kontrol etmek 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 hoş bir hafif çapraz tarayıcı JavaScript XML ayrıştırıcıdır. Nesneye yöneliktir ve çok sayıda örneğe sahiptir, ayrıca API belgelenmiştir. Oldukça yeni, ama şimdiye kadar projelerimden birinde güzel çalıştı. Bu konuda sevdiğim bir şey, XML'yi doğrudan dizelerden veya URL'lerden okuyacağı ve XML'yi JSON'a dönüştürmek için de kullanabilmeniz.

Marknote ile yapabileceklerinize bir örnek:

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") + "'"
    );
}

Görünüşe göre marknote saf bir javascript ayrıştırıcısı uygular. Bir tarayıcıda, node.js'de veya bağımsız bir javascript motorunda nerede kullanılırsa kullanılsın, herhangi bir javascript motoruyla uyumlu olması gerektiği anlamına gelir ...
Coyote

8

Her zaman aşağıda IE ve Firefox'ta çalışan yaklaşımı kullandım.

Örnek 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);
      }
    }
  }
}

Bu <fruit> değer </fruit> durumunuz olsaydı nasıl bir değer elde edersiniz?
Siblja

1
@Siblja innerTextyerine kullanmanız gerekiyorgetAttribute()
Manux22


2

Lütfen XML DOM Ayrıştırıcısına ( W3Schools ) bir göz atın . XML DOM ayrıştırma hakkında bir öğretici. Gerçek DOM ayrıştırıcısı tarayıcıdan tarayıcıya farklılık gösterir, ancak DOM API standartlaştırılmıştır ve aynı kalır (daha fazla veya daha az).

Alternatif olarak , kendinizi Firefox ile kısıtlayabiliyorsanız E4X kullanın . Kullanımı nispeten daha kolaydır ve 1.6 sürümünden beri JavaScript'in bir parçasıdır. İşte küçük bir örnek kullanım ...

//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.

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>

Daha fazla bilgi için bu http://www.easycodingclub.com/xml-parser-in-javascript/javascript-tutorials/ adresine bakın.


0

Feragatname : fast-xml-parser oluşturdum

Bir XML dizesini JS / JSON nesnesi veya ara geçiş nesnesine ayrıştırmak için fast-xml-ayrıştırıcı oluşturdum . Tüm tarayıcılarda uyumlu olması beklenir (ancak yalnızca Chrome, Firefox ve IE'de test edilmiştir).

kullanım

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);

Not : DOM ayrıştırıcısını kullanmaz, ancak RE'yi kullanarak dizeyi ayrıştırır ve JS / JSON nesnesine dönüştürür.

Çevrimiçi deneyin , CDN


-1

Ayrıca xml dizesini değiştirmek için jquery işlevi ($. ParseXML) aracılığıyla da yapabilirsiniz.

örnek 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'))
})
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.