การแยกวิเคราะห์ XML ของสตริงตัวแปรใน JavaScript


204

ฉันมี สตริงตัวแปรที่มี XML ที่มีรูปแบบถูกต้องและถูกต้อง ฉันต้องใช้รหัส JavaScript เพื่อแยกวิเคราะห์ฟีดนี้

ฉันจะทำสิ่งนี้ให้สำเร็จโดยใช้โค้ด JavaScript ที่เข้ากันได้กับเบราว์เซอร์ได้อย่างไร

คำตอบ:


90

ปรับปรุง: สำหรับคำตอบที่ถูกต้องเพิ่มเติมโปรดดูคำตอบของทิมลง

ยกตัวอย่างเช่น Internet Explorer และเบราว์เซอร์ที่ใช้ Mozilla แสดงวัตถุที่แตกต่างกันสำหรับการแยกวิเคราะห์ XML ดังนั้นจึงควรใช้เฟรมเวิร์ก JavaScript เช่นjQueryเพื่อจัดการกับความแตกต่างของเบราว์เซอร์ข้าม

ตัวอย่างพื้นฐานจริง ๆ คือ:

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

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

หมายเหตุ: ตามที่ระบุไว้ในความคิดเห็น; jQuery ไม่ได้ทำการแยกวิเคราะห์ XML แต่อย่างใดมันอาศัยวิธี DOM innerHTML และจะแยกวิเคราะห์เหมือนว่ามันจะเป็น HTML ใด ๆ ดังนั้นจึงควรใช้ความระมัดระวังเมื่อใช้ชื่อองค์ประกอบ HTML ใน XML ของคุณ แต่ฉันคิดว่ามันใช้งานได้ค่อนข้างดีสำหรับการแยกวิเคราะห์ XML อย่างง่าย แต่อาจไม่แนะนำให้ใช้การแยกวิเคราะห์ XML แบบเข้มข้นหรือแบบไดนามิกที่คุณไม่ต้องเปิดเผยล่วงหน้าว่า XML จะลงมาอย่างไรและการทดสอบนี้จะแยกวิเคราะห์ทุกอย่างตามที่คาดไว้


6
รหัสสำหรับสรุปความแตกต่างในการแยกวิเคราะห์ XML ระหว่าง IE และเบราว์เซอร์อื่น ๆ นั้นเป็นเพียงเล็กน้อยบรรทัดดังนั้นจึงไม่คุ้มกับการใช้ 50K ของ jQuery การจัดการ DOM ของ XML ที่ได้นั้นเป็นเรื่องอื่น
Tim Down

7
และสิ่งที่ฉันไม่ได้ตระหนักในขณะโพสต์ความคิดเห็นก่อนหน้าของฉันคือ jQuery ไม่ได้แยกวิเคราะห์ XML มันเพียงกำหนดมันเป็นinnerHTMLคุณสมบัติขององค์ประกอบซึ่งไม่น่าเชื่อถือเลย
Tim Down

โปรดทราบว่า JQuery ไม่สนับสนุน XML เนมสเปซ ดูzachleat.com/web/2008/05/10/selecting-xml-with-javascript
mikemaccana

10
คำตอบนี้ผิด ดูstackoverflow.com/questions/2124924/… , stackoverflow.com/questions/2908899/… , คำตอบของ @Tim Down และเอกสาร jQueryที่ระบุ: "โปรดทราบว่า [ jQuery()] จะแยก HTML ไม่ใช่ XML"
Crescent Fresh

2
@SanderVersluys: เนื่องจากผู้เขียนไม่ยอมรับคำตอบอื่นฉันจะรวมข้อความในคำตอบของคุณที่เชื่อมโยงไปยังคำตอบที่ถูกต้องของ @ TimDown ด้วยวิธีนี้ผู้คนไม่จำเป็นต้องอ่านความคิดเห็นเหล่านี้เพื่อค้นหาคำตอบที่ถูกต้อง
มีความรู้สึก

321

อัปเดตคำตอบสำหรับปี 2560

ต่อไปนี้จะแยกสตริง XML ลงในเอกสาร XML ในเบราว์เซอร์หลักทั้งหมด ถ้าคุณไม่ต้องการการสนับสนุนสำหรับ IE <= 8 หรือเบราว์เซอร์ที่ไม่ชัดเจนคุณสามารถใช้ฟังก์ชั่นต่อไปนี้:

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

หากคุณต้องการรองรับ IE <= 8 สิ่งต่อไปนี้จะทำงาน:

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

เมื่อคุณได้Documentรับผ่านparseXmlคุณสามารถใช้วิธี / คุณสมบัติการสำรวจเส้นทาง DOM ปกติเช่นchildNodesและgetElementsByTagName()เพื่อรับโหนดที่คุณต้องการ

ตัวอย่างการใช้งาน:

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

หากคุณใช้ jQuery จากเวอร์ชัน 1.5 คุณสามารถใช้parseXML()วิธีการในตัวซึ่งเหมือนกับฟังก์ชันด้านบน

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

56
ฉันยอมรับคำตอบนี้ควรได้รับการยอมรับ คำตอบของฉันเก่ามากตั้งแต่วันแรกฉันมักจะพบว่ามันอยากรู้อยากเห็นมันยังได้รับ upvotes ทุกคนชื่นชอบที่จะลบคำตอบที่ฉันยอมรับ? และระบบการลงคะแนนมีข้อบกพร่องหรือไม่ โหวตคนนี้!
Sander Versluys

@SanderVersluys: คุณสามารถลบคำตอบของคุณ?
Witman

1
ต้องลงคะแนนให้คุณเพราะบอกว่าไม่มี 'คำตอบที่ดีอื่น ๆ ' @SanderVersluys คำตอบทำงานได้ดีในกรณีของฉัน สิ่งที่ไม่ดีเกี่ยวกับเรื่องนั้นฉันไม่รู้
eric

2
@EricTurner: ฉันยืนหยัดและ Sander เองก็ปฏิเสธคำตอบของเขา เอกสาร jQuery บอกคุณไม่ได้ที่จะใช้$()สำหรับการแยก XML อ่านความคิดเห็นเพิ่มเติมอย่างละเอียด: มันไม่ทำงานในหลาย ๆ สถานการณ์
Tim Down

1
@Doldold: ฉันเคยเห็นมันทั้งสองทางบนเว็บและฉันสงสัยว่ามันทำงานได้ทั้งสองวิธี ที่ใกล้ที่สุดที่ฉันสามารถหาคำตอบที่มีสิทธิ์คือmsdn.microsoft.com/en-us/library/ms761398(v=vs.85).aspxซึ่งบอกว่าควรใช้บูลีน อย่างไรก็ตามและมูลค่าเท่าไหร่ที่คุณทำในสิ่งนี้ขึ้นอยู่กับคุณทั้งหมดวิธีของ jQueryparseXML()ใช้สตริง ฉันระวังการเปลี่ยนคำตอบเล็กน้อยเพราะตอนนี้ฉันไม่มีวิธีทดสอบที่ง่าย
Tim Down

19

ตัวอย่างส่วนใหญ่บนเว็บ (และบางรายการที่แสดงด้านบน) แสดงวิธีโหลด XML จากไฟล์ในลักษณะที่เข้ากันได้กับเบราว์เซอร์ สิ่งนี้พิสูจน์ได้ง่ายยกเว้นในกรณีของ Google Chrome ที่ไม่สนับสนุนdocument.implementation.createDocument()วิธีการนี้ เมื่อใช้ Chrome เพื่อโหลดไฟล์ XML ลงในวัตถุ XmlDocument คุณต้องใช้วัตถุ XmlHttp inbuilt แล้วโหลดไฟล์โดยผ่าน URI

ในกรณีของคุณสถานการณ์แตกต่างกันเนื่องจากคุณต้องการโหลด XML จากตัวแปรสตริงไม่ใช่ URL สำหรับข้อกำหนดนี้ Chrome คาดว่าจะทำงานเช่นเดียวกับ Mozilla (หรือที่ฉันเคยได้ยิน) และสนับสนุนวิธี parseFromString ()

นี่คือฟังก์ชั่นที่ฉันใช้ (เป็นส่วนหนึ่งของไลบรารีความเข้ากันได้ของเบราว์เซอร์ที่ฉันกำลังสร้าง):

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
ฉันตระหนักถึงความคิดเห็นที่ขัดแย้งเกี่ยวกับการดมกลิ่นเบราว์เซอร์และนั่นคือเหตุผลที่ฉันไม่ได้รวมฟังก์ชั่นนั้นไว้ที่นี่ อย่างไรก็ตามยังไม่ได้รับการยอมรับว่าผิด ในกรณีใด ๆ นี้เป็นชี้นำตัวอย่างเช่น
Cerebrus

1
ฉันเชื่อว่ามันผิดที่คุณไม่สามารถรับประกันได้ว่ามันถูกต้อง ทุกคนสามารถหลอกสตริง UA และเป็นที่น่าสงสัยว่าเบราว์เซอร์ที่ไม่ใช่ IE ทุกตัวรองรับ DOMParser และการดมกลิ่นเบราว์เซอร์ของคุณนั้นสมบูรณ์แบบ และยิ่งกว่านั้นมันง่ายกว่าที่จะทำในสิ่งที่ถูกต้อง:if(window.ActiveXObject){...}
1j01

ดังนั้นตอนนี้ IE9 + รองรับ DOMParserคุณจะสนับสนุนได้อย่างไร -1 สำหรับสิ่งที่ @ 1j01 พูด 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เป็นตัวแยกวิเคราะห์ XML JavaScript ข้ามเบราว์เซอร์ที่มีน้ำหนักเบา มันเป็นแบบเชิงวัตถุและมีตัวอย่างมากมายรวมถึงเอกสารAPI มันค่อนข้างใหม่ แต่ก็ใช้งานได้ดีในหนึ่งในโครงการของฉัน สิ่งหนึ่งที่ฉันชอบเกี่ยวกับมันคือมันจะอ่าน XML โดยตรงจากสตริงหรือ URL และคุณยังสามารถใช้มันเพื่อแปลง XML เป็น JSON

นี่คือตัวอย่างของสิ่งที่คุณสามารถทำได้กับ Marknote:

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

ดูเหมือนว่าmarknote จะใช้ตัวแยกวิเคราะห์จาวาสคริปต์ที่บริสุทธิ์ มันหมายความว่ามันควรจะเข้ากันได้กับเครื่องมือจาวาสคริปต์ทุกที่ที่ใช้ในเบราว์เซอร์ใน node.js หรือในเครื่องยนต์จาวาสคริปต์แบบสแตนด์อโลน ...
โคโยตี้

8

ฉันใช้วิธีการด้านล่างซึ่งใช้งานได้ใน IE และ Firefox เสมอ

ตัวอย่าง 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);
      }
    }
  }
}

คุณจะรับค่าอย่างไรถ้าคุณมีสถานการณ์เช่นนี้ <fruit> ค่า </fruit>
Siblja

1
@Slibja คุณต้องใช้innerTextแทนgetAttribute()
Manux22


2

โปรดดูXML DOM Parser ( W3Schools ) มันเป็นบทเรียนเกี่ยวกับการแยกวิเคราะห์ XML DOM ตัวแยกวิเคราะห์ DOM ที่แท้จริงแตกต่างจากเบราว์เซอร์ไปยังเบราว์เซอร์ แต่ DOM API นั้นเป็นมาตรฐานและยังคงเหมือนเดิม (มากหรือน้อย)

หรือใช้E4Xหากคุณสามารถจำกัดตัวเองไว้ที่ Firefox มันค่อนข้างใช้งานง่ายและเป็นส่วนหนึ่งของ JavaScript ตั้งแต่รุ่น 1.6 นี่คือตัวอย่างการใช้งานขนาดเล็ก ...

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

สำหรับข้อมูลเพิ่มเติมอ้างอิงhttp://www.easycodingclub.com/xml-parser-in-javascript/javascript-tutorials/นี้


0

คำเตือน : ฉันสร้างfast-xml-parser

ฉันสร้างfast-xml-parserเพื่อแยกสตริง XMLลงในวัตถุ JS / JSON หรือวัตถุสำรวจเส้นทางกลาง คาดว่าจะเข้ากันได้กับเบราว์เซอร์ทั้งหมด (ทดสอบบน Chrome, Firefox และ IE เท่านั้น)

การใช้

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

บันทึก : มันไม่ได้ใช้ตัวแยกวิเคราะห์ DOM แต่แยกวิเคราะห์สตริงโดยใช้ RE และแปลงเป็นวัตถุ JS / JSON

ลองมันออนไลน์ , CDN


-1

คุณยังสามารถใช้ฟังก์ชัน jquery ($. parseXML) เพื่อจัดการสตริง xml

ตัวอย่างจาวาสคริปต์:

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'))
})
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.