使用JavaScript对变量字符串进行XML解析


204

我有一个包含格式正确且有效的XML 的可变字符串。我需要使用JavaScript代码来解析此供稿。

如何使用(浏览器兼容)JavaScript代码来完成此操作?

Answers:


90

更新:有关更正确的答案,请参见Tim Down的答案

Internet Explorer和基于Mozilla的浏览器为XML解析提供了不同的对象,因此明智的是使用jQuery之类的JavaScript框架来处理跨浏览器的差异。

一个非常基本的示例是:

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

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

注意:如评论中所指出;jQuery实际上并没有执行任何XML解析,它依赖于DOM innerHTML方法,并且将像解析任何HTML一样解析它,因此在XML中使用HTML元素名称时要格外小心。但是我认为它对于简单的XML“解析”效果相当好,但是对于密集或“动态”的XML解析,可能不建议您这样做,因为您不需要预先了解XML会下降什么,并且可以测试是否按预期进行解析。


6
摘录IE和其他浏览器之间XML解析的区别的代码是几条琐碎的代码,因此不值得单独依靠jQuery 50K。处理生成的XML的DOM是另一回事。
Tim Down

7
在发布我之前的评论时,我没有意识到的是jQuery甚至没有解析XML,它只是将XML分配为innerHTML元素的属性,这根本不可靠。
Tim Down

请注意,JQuery不支持XML名称空间。看到zachleat.com/web/2008/05/10/selecting-xml-with-javascript
mikemaccana 2011年

10
这个答案是错误的。见stackoverflow.com/questions/2124924/...stackoverflow.com/questions/2908899/...,@Tim唐氏答案和jQuery文档本身它指出:“需要注意的是[ jQuery()]解析HTML,不是 XML”
新月新鲜的

2
@SanderVersluys:由于作者不接受其他答案,因此我会在您的答案中加入一条注释,链接至@TimDown的正确答案。这样,人们不必阅读所有这些注释即可找到正确的答案。
有意义的2012年

321

更新了2017年的答案

下面将在所有主要浏览器中将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获得了via 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
我同意,这应该被接受。我的答案从成立之初起就太老了,我总是觉得很好奇它仍然会被投票。有人赞成删除我接受的答案吗?投票系统有缺陷吗?支持这个人!
Sander Versluys

@SanderVersluys:您可以删除答案吗?
Witman'3

1
不得不拒绝您说“没有其他体面的答案”。@SanderVersluys的答案在我的情况下效果很好。我不知道这有什么不正当之处。
eric 2012年

2
@EricTurner:我支持,Sander本人拒绝了他的回答。jQuery文档告诉您不要$()用于XML解析。请更仔细地阅读注释:在许多情况下,它根本不起作用。
Tim Down'4

1
@DWoldrich:我已经在网上看到了这两种方式,并且我怀疑它可以同时使用。我可以找到最接近权威答案的地方是msdn.microsoft.com/en-us/library/ms761398(v=vs.85).aspx,其中说应该使用布尔值。但是,在其中放置多少值完全取决于您,jQuery的parseXML()方法使用字符串。我对更改答案有些谨慎,因为我现在没有简单的方法可以对其进行测试。
Tim Down

19

网络上的大多数示例(以及上面提供的一些示例)都显示了如何以浏览器兼容方式从文件加载XML 。事实证明这很容易,但不支持该document.implementation.createDocument()方法的Google Chrome浏览器除外。使用Chrome时,为了将XML文件加载到XmlDocument对象中,您需要使用内置的XmlHttp对象,然后通过传递其URI来加载文件。

在您的情况下,情况有所不同,因为您要从字符串变量而不是URL 加载XML 。但是,对于这一要求,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,您将如何支持它?@ 1j01的意思是-1。您只需要检查一下即可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)') }
安妮

13

Marknote是一个不错的轻量级跨浏览器JavaScript XML解析器。它是面向对象的,并且有很多示例,并且记录了API。这是相当新的东西,但是到目前为止,它在我的一个项目中运行良好。我喜欢它的一件事是它将直接从字符串或URL读取XML,并且您还可以使用它将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实现了纯JavaScript解析器。这意味着它应该与任何JavaScript引擎,无论它是在浏览器中使用,在node.js中或在独立的JavaScript引擎兼容...

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> value </ fruit>,您将如何取值?
Siblja 2011年

1
@Siblja您需要使用innerText而不是getAttribute()
Manux22 '16


2

请看一下XML DOM解析器W3Schools)。这是有关XML DOM解析的教程。实际的DOM解析器因浏览器而异,但是DOM API是标准化的,并且保持不变(或多或少)。

如果可以限制自己使用Firefox,也可以使用E4X。自1.6版以来,它相对易于使用,并且是JavaScript的一部分。这是一个小样本用法...

//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字符串

示例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'))
})
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.