Phân tích cú pháp XML của một chuỗi biến trong JavaScript


204

Tôi có một chuỗi biến chứa XML hợp lệ và hợp lệ. Tôi cần sử dụng mã JavaScript để phân tích nguồn cấp dữ liệu này.

Làm cách nào tôi có thể thực hiện việc này bằng mã JavaScript (tương thích với trình duyệt)?

Câu trả lời:


90

Cập nhật: Để có câu trả lời chính xác hơn, hãy xem câu trả lời của Tim Down .

Internet Explorer và, ví dụ, các trình duyệt dựa trên Mozilla phơi bày các đối tượng khác nhau để phân tích cú pháp XML, vì vậy nên sử dụng khung JavaScript như jQuery để xử lý các khác biệt giữa các trình duyệt.

Một ví dụ thực sự cơ bản là:

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

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

Lưu ý: Như đã chỉ ra trong các ý kiến; jQuery không thực sự làm bất kỳ phân tích cú pháp XML nào, nó dựa vào phương thức DOM bên trong DOM và sẽ phân tích nó giống như bất kỳ HTML nào, vì vậy hãy cẩn thận khi sử dụng tên thành phần HTML trong XML của bạn. Nhưng tôi nghĩ rằng nó hoạt động khá tốt đối với 'phân tích cú pháp' XML đơn giản, nhưng có lẽ nó không được đề xuất cho phân tích cú pháp XML chuyên sâu hoặc 'động' khi bạn không trả lời những gì XML sẽ xuất hiện và điều này sẽ kiểm tra nếu mọi thứ phân tích như mong đợi.


6
Mã để trừu tượng hóa sự khác biệt trong phân tích cú pháp XML giữa IE và các trình duyệt khác là một vài dòng tầm thường, do đó, không đáng để tự mình sử dụng 50K jQuery. Thao tác với DOM của XML kết quả là một vấn đề khác.
Tim Down

7
Và một điều tôi không nhận ra tại thời điểm đăng bình luận trước đó của mình là jQuery thậm chí không phân tích cú pháp XML, nó chỉ đơn giản gán nó là thuộc innerHTMLtính của một phần tử, điều này hoàn toàn không đáng tin cậy.
Tim Down

Lưu ý rằng JQuery không hỗ trợ các không gian tên XML. Xem zachleat.com/web/2008/05/10/selecting-xml-with-javascript
mikemaccana

10
Câu trả lời này là sai. Xem stackoverflow.com/questions/2124924/ trên , stackoverflow.com/questions/2908899/ Lời , câu trả lời của @Tim Down và chính tài liệu jQuery có ghi: "Lưu ý rằng [ jQuery()] phân tích cú pháp HTML, không phải XML"
Crescent Fresh

2
@SanderVersluys: vì tác giả không chấp nhận câu trả lời khác, tôi sẽ bao gồm một ghi chú trong câu trả lời của bạn liên kết đến câu trả lời đúng của @ TimDown . Bằng cách đó, mọi người không cần phải đọc tất cả những bình luận này để tìm ra câu trả lời chính xác.
Nhận thức

321

Cập nhật câu trả lời cho năm 2017

Sau đây sẽ phân tích một chuỗi XML thành một tài liệu XML trong tất cả các trình duyệt chính. Trừ khi bạn cần hỗ trợ cho IE <= 8 hoặc một số trình duyệt tối nghĩa, bạn có thể sử dụng chức năng sau:

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

Nếu bạn cần hỗ trợ IE <= 8, việc sau sẽ thực hiện công việc:

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

Khi bạn có Documentđược thông qua parseXml, bạn có thể sử dụng các phương thức / thuộc tính truyền tải DOM thông thường như childNodesgetElementsByTagName() để có được các nút bạn muốn.

Ví dụ sử dụng:

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

Nếu bạn đang sử dụng jQuery, từ phiên bản 1.5, bạn có thể sử dụng parseXML()phương thức tích hợp sẵn của nó , giống như chức năng ở trên.

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

56
Tôi đồng ý, điều này nên được chấp nhận câu trả lời. Câu trả lời của tôi đã quá cũ từ những ngày đầu, tôi luôn thấy tò mò rằng nó vẫn được nâng cấp. Bất cứ ai ủng hộ loại bỏ câu trả lời được chấp nhận của tôi? Và hệ thống bỏ phiếu có thiếu sót? Upvote người này!
Sander Versluys

@SanderVersluys: Bạn có thể xóa câu trả lời của mình không?
Witman

1
Phải đánh giá thấp bạn vì đã nói rằng "không có câu trả lời tử tế nào khác". Câu trả lời @SanderVersluys hoạt động tốt trong trường hợp của tôi. Những gì không tốt về điều đó, tôi không biết.
eric

2
@EricTurner: Tôi đứng bên cạnh và chính Sander đã từ chối câu trả lời của anh ấy. Các tài liệu jQuery bảo bạn không sử dụng $()để phân tích cú pháp XML . Đọc các bình luận cẩn thận hơn: đơn giản là nó không hoạt động trong nhiều tình huống.
Tim xuống

1
@DWoldrich: Tôi đã thấy cả hai cách trên web và tôi nghi ngờ nó hoạt động theo cả hai cách. Câu trả lời gần nhất mà tôi có thể tìm thấy cho một câu trả lời có thẩm quyền là msdn.microsoft.com/en-us/l Library / ms761398 (v = vs85) .aspx , trong đó nên sử dụng Boolean. Tuy nhiên, và bạn đặt bao nhiêu giá trị trong việc này hoàn toàn tùy thuộc vào bạn, phương thức của jQueryparseXML() sử dụng một chuỗi. Tôi hơi cảnh giác khi thay đổi câu trả lời vì tôi không có cách nào dễ dàng để kiểm tra nó ngay bây giờ.
Tim Down

19

Hầu hết các ví dụ trên web (và một số trình bày ở trên) cho thấy cách tải XML từ một tệp theo cách tương thích với trình duyệt. Điều này chứng tỏ dễ dàng, ngoại trừ trong trường hợp Google Chrome không hỗ trợ document.implementation.createDocument()phương pháp. Khi sử dụng Chrome, để tải tệp XML vào đối tượng XmlDocument, bạn cần sử dụng đối tượng XmlHttp sẵn có và sau đó tải tệp bằng cách chuyển URI của nó.

Trong trường hợp của bạn, kịch bản là khác nhau, vì bạn muốn tải XML từ một biến chuỗi chứ không phải URL. Tuy nhiên, đối với yêu cầu này, Chrome được cho là hoạt động giống như Mozilla (hoặc tôi đã nghe) và hỗ trợ phương thức parseFromString ().

Đây là một chức năng tôi sử dụng (nó là một phần của thư viện tương thích Trình duyệt tôi hiện đang xây dựng):

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
Tôi biết các ý kiến ​​gây tranh cãi liên quan đến Trình duyệt đánh hơi và đó là lý do tôi không đưa chức năng đó vào đây. Tuy nhiên, nó đã không được thiết lập rằng nó là SAI. Trong mọi trường hợp, đây là một ví dụ gợi ý .
Cerebrus

1
Tôi tin rằng nó sai ở chỗ bạn không thể đảm bảo rằng nó đúng. Bất cứ ai cũng có thể giả mạo các chuỗi UA và nghi ngờ rằng MỌI trình duyệt không phải IE hỗ trợ DOMParser và trình duyệt của bạn đánh hơi là HOÀN HẢO. Và bên cạnh đó, việc thực hiện nó đúng cách dễ dàng hơn nhiều:if(window.ActiveXObject){...}
1j01

Vậy bây giờ IE9 + hỗ trợ DOMParser , bạn sẽ hỗ trợ như thế nào? -1 cho những gì @ 1j01 đang nói. Tất cả bạn cần kiểm tra là 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 là một trình phân tích cú pháp JavaScript XML đa trình duyệt nhẹ. Nó hướng đối tượng và nó có rất nhiều ví dụ, cộng với API được ghi lại. Nó khá mới, nhưng nó đã hoạt động tốt trong một trong những dự án của tôi cho đến nay. Một điều tôi thích ở đây là nó sẽ đọc XML trực tiếp từ các chuỗi hoặc URL và bạn cũng có thể sử dụng nó để chuyển đổi XML thành JSON.

Đây là một ví dụ về những gì bạn có thể làm với 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") + "'"
    );
}

Có vẻ như marknote thực hiện một trình phân tích cú pháp javascript thuần túy. Điều đó có nghĩa là nó phải tương thích với bất kỳ công cụ javascript nào, bất cứ nơi nào nó được sử dụng trong trình duyệt, trong node.js hoặc trong một công cụ javascript độc lập ...
Coyote

8

Tôi đã luôn sử dụng cách tiếp cận dưới đây hoạt động trong IE và Firefox.

Ví dụ 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);
      }
    }
  }
}

Bạn sẽ nhận một giá trị như thế nào nếu bạn gặp tình huống này <fruit> value </ fruit>?
Siblja

1
@Siblja bạn cần sử dụng innerTextthay vìgetAttribute()
Manux22


2

Vui lòng xem XML DOM Parser ( W3Schools ). Đây là một hướng dẫn về phân tích cú pháp XML DOM. Trình phân tích cú pháp DOM thực tế khác nhau từ trình duyệt này sang trình duyệt khác nhưng API DOM được chuẩn hóa và giữ nguyên (ít nhiều).

Hoặc sử dụng E4X nếu bạn có thể hạn chế sử dụng Firefox. Nó tương đối dễ sử dụng hơn và nó là một phần của JavaScript kể từ phiên bản 1.6. Đây là một cách sử dụng mẫu nhỏ ...

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

Để biết thêm thông tin, hãy tham khảo http://www.easycodingclub.com/xml-parser-in-javascript/javascript-tutorials/


0

Tuyên bố miễn trừ trách nhiệm : Tôi đã tạo trình phân tích cú pháp nhanh xml

Tôi đã tạo trình phân tích cú pháp nhanh-xml để phân tích chuỗi XML thành đối tượng JS / JSON hoặc đối tượng truyền tải trung gian. Nó dự kiến ​​sẽ tương thích trong tất cả các trình duyệt (tuy nhiên chỉ được thử nghiệm trên Chrome, Firefox và IE).

Sử dụng

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

Lưu ý : Nó không sử dụng trình phân tích cú pháp DOM mà phân tích chuỗi bằng RE và chuyển đổi nó thành đối tượng JS / JSON.

Dùng thử trực tuyến , CDN


-1

Bạn cũng có thể thông qua hàm jquery ($. ParseXML) để thao tác chuỗi xml

ví dụ 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'))
})
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.