如何使用jQuery对具有名称空间的XML进行解析


82

我是jQuery新手,想解析XML文档。

我可以使用默认名称空间解析常规XML,但可以使用以下XML解析该XML:

<xml xmlns:s="uuid:BDC6E3F0-6DA3-11d1-A2A3-00AA00C14882" xmlns:dt="uuid:C2F41010-65B3-11d1-A29F-00AA00C14882" xmlns:rs="urn:schemas-microsoft-com:rowset" xmlns:z="#RowsetSchema">
   <s:Schema id="RowsetSchema">
     <s:ElementType name="row" content="eltOnly" rs:CommandTimeout="30">
       <s:AttributeType name="ows_ID" rs:name="ID" rs:number="1">
        <s:datatype dt:type="i4" dt:maxLength="4" />
      </s:AttributeType>
       <s:AttributeType name="ows_DocIcon" rs:name="Type" rs:number="2">
        <s:datatype dt:type="string" dt:maxLength="512" />
      </s:AttributeType>
       <s:AttributeType name="ows_LinkTitle" rs:name="Title" rs:number="3">
        <s:datatype dt:type="string" dt:maxLength="512" />
      </s:AttributeType>
       <s:AttributeType name="ows_ServiceCategory" rs:name="Service Category" rs:number="4">
        <s:datatype dt:type="string" dt:maxLength="512" />
      </s:AttributeType>
    </s:ElementType>
  </s:Schema>
   <rs:data>
    <z:row ows_ID="2" ows_LinkTitle="Sample Data 1" />
    <z:row ows_ID="3" ows_LinkTitle="Sample Data 2" />
    <z:row ows_ID="4" ows_LinkTitle="Sample Data 3" />
  </rs:data>
</xml>

我真正想要的只是<z:row>

到目前为止,我一直在使用:

$.get(xmlPath, {}, function(xml) {
    $("rs:data", xml).find("z:row").each(function(i) {
        alert("found zrow");
    });
}, "xml");

真的没有运气。有任何想法吗?


省略名称空间前缀对我有用。看到这个答案:stackoverflow.com/a/25089647/2539811
Vincil Bishop

Answers:


135

我知道了。

原来,它需要\\逃脱冒号。

$.get(xmlPath, {}, function(xml) {
    $("rs\\:data", xml).find("z\\:row").each(function(i) {
        alert("found zrow");
    });
}, "xml");

正如Rich所指出的:

更好的解决方案不需要转义,并且可以在所有“现代”浏览器上使用:

.find("[nodeName=z:row]")

2
$('[nodeName=rs:data]', xml).find('[nodeName=z:row]')-在WebKit下可与1.3.2一起使用(转义的冒号方法显然不适用)
gnarf 2010年

2
这似乎已停止在jQuery 1.4.4版中工作,我认为这意味着jQuery具有更好的XML名称空间支持。为安全起见,此方法有效$('[nodeName=rs:data],data')
Josh Pearce

15
现在jQuery 1.7已经发布,最后一个解决方案不再起作用。有什么新方法?
Gapipro 2011年

3
在jQuery 1.8.x中,它不再起作用。它应该有一个自定义的伪类兼容性的解决方法来实现,如解释在这里
Miere 2012年

5
尽管这个回答给定XML文档的问题,我想提醒大家的是,前缀喜欢rsdt或者s是真的不命名空间。命名空间是文件顶部的URN。前缀只是文档作者选择的别名,以使内容简短。可以使用完全不同的前缀来创建与相同名称空间匹配的相同文档。我鼓励大家寻找能够理解名称空间的API,而不要在查询中使用前缀。例如,在浏览器DOM API中,您可以使用getElementByTagNameNS()getAttributeNS()
sergiopereira

35

我花了几个小时阅读有关插件和各种解决方案的文章,但运气不佳。

ArnisAndy发布了一个jQuery讨论的链接,提供了这个答案,我可以确认它在Chrome(v18.0),FireFox(v11.0),IE(v9.08)和Safari(v5.1.5)中对我有用)使用jQuery(v1.7.2)。

我正在尝试抓取一个内容为<content:encoded>的WordPress feed,这对我有用:

content: $this.find("content\\:encoded, encoded").text()

3
这是唯一使用最新jQuery(相同版本)对我可靠地工作的软件,谢谢!
Dominic K

2
这为我工作,而我用了一个.each()通过循环遍历item元素:$('dc\\:creator, creator', this).text()。虽然,我不确定为什么, creator需要额外的东西,而dc\\:creator不仅仅是工作。
Fillip Peyton 2014年

20

如果您使用的是jquery 1.5,则必须在节点选择器属性值周围添加引号以使其起作用:

.find('[nodeName="z:row"]')

19

尽管以上答案似乎是正确的,但在Webkit浏览器(Safari,Chrome)中不起作用。我相信一个更好的解决方案是:

.find("[nodeName=z:myRow, myRow]")    

5
这似乎已停止在jQuery 1.4.4版中工作,我认为这意味着jQuery具有更好的XML名称空间支持。为安全起见,此方法有效$('[nodeName=rs:data],data')
Josh Pearce

16

如果有人需要在没有jQuery的情况下(仅使用普通Javascript)和Google Chrome(Webkit)来执行此操作,这是我经过大量研究和测试后才发现能够运行的唯一方法。

parentNode.getElementsByTagNameNS("*", "name");

这将可用于检索以下节点:<prefix:name>。如您所见,前缀或名称空间被省略,并且如果标签名称为,它将匹配具有不同名称空间的元素name。但是希望这对您来说不会成为问题。

这些都不适合我(我正在开发Google Chrome扩展程序):

getElementsByTagNameNS("prefix", "name")

getElementsByTagName("prefix:name")

getElementsByTagName("prefix\\:name")

getElementsByTagName("name")

编辑:经过一番睡眠,我发现了一种解决方法:)此函数返回匹配完整的第一个节点,nodeName例如<prefix:name>

// Helper function for nodes names that include a prefix and a colon, such as "<yt:rating>"
function getElementByNodeName(parentNode, nodeName)
{   
    var colonIndex = nodeName.indexOf(":");
    var tag = nodeName.substr(colonIndex + 1);
    var nodes = parentNode.getElementsByTagNameNS("*", tag);
    for (var i = 0; i < nodes.length; i++)
    {
        if (nodes[i].nodeName == nodeName) return nodes[i]
    }
    return undefined;
}

如果您需要返回所有匹配的元素,可以轻松地对其进行修改。希望能帮助到你!


14

上面的解决方案都无法正常工作。我发现了这一点,并对其速度进行了改进。只需添加它,就像一个魅力:

$.fn.filterNode = function(name) {
    return this.find('*').filter(function() {
       return this.nodeName === name;
    });
};

用法:

var ineedthatelementwiththepsuedo = $('someparentelement').filterNode('dc:creator');

来源:http//www.steveworkman.com/html5-2/javascript/2011/improving-javascript-xml-node-finding-performance-by-2000/


谢谢您的摘要-这非常有帮助/可以解决问题。
吉尔曼(Gilman)


3

值得注意的是,从jQuery 1.7开始,用于查找命名空间元素的一些变通方法存在问题。有关更多信息,请参见以下链接:


如果性能很重要,那么最好的解决方案是选择不带jQuery的标签。进行比较,请参阅:jsperf.com/node-vs-double-select/13

3

在评论中找到解决方案:使用jQuery $()。find解析具有名称空间的XML

使用冒号之后的节点名称的后半部分对我有用。使用.find(“ lat”)代替.find(“ geo \:lat”),它对我有用


我的设置:

  • 镀铬42
  • jQuery 2.1.3

XML示例(来自Google Contacts API的代码段):

<entry>
  <id>http://www.google.com/m8/feeds/contacts/mstefanow%40gmail.com/base/0</id>
  <gd:email rel="http://schemas.google.com/g/2005#other" address="email@example.com" primary="true"/>
</entry>

解析代码:

var xmlDoc = $.parseXML( xml );
var $xml = $( xmlDoc );
var $emailNode = $xml.find( "email" );
$("#email").html($emailNode.attr("address"));

网址:http://plnkr.co/edit/l8VzyDq1NHtn5qC9zTjf?p = preview


很高兴我能够提供帮助:)
Mike Grace 2015年

2

jQuery 1.7不适用于以下内容:

$(xml).find("[nodeName=a:IndexField2]")

我确实可以在Chrome,Firefox和IE中使用的一种解决方案是基于一种方法可以在IE中工作,而另一种可以在Chrome中工作的事实是使用在IE中工作的选择器和在Chrome中工作的选择器:

$(xml).find('a\\\\:IndexField2, IndexField2')

在IE中,此操作返回使用名称空间的节点(Firefox和IE要求使用名称空间),而在Chrome中,选择器基于非命名空间选择器返回节点。我尚未在Safari中对其进行测试,但是它应该可以工作,因为它在Chrome中可以工作。


2

我的解决方案(因为我使用了Php代理)是将_名称空间替换为_ ...,因此不再存在名称空间问题;-)

把事情简单化 !



2

截至2016年初,对我而言,以下语法可用于jQuery 1.12.0:

  • IE 11(11.0.9600.18204,更新11.0.28,KB3134815): .find("z\\:row")
  • Firefox 44.0.2: .find("z\\:row")
  • Chrome 44.0.2403.89m: .find("row")

该语法.find("[nodeName=z:row]")在上述任何浏览器中均不起作用。我发现无法在Chrome中应用名称空间。

综上所述,以下语法可在上述所有浏览器中使用: .find("row,z\\:row")


1

如上所述,当前的jQuery浏览器/版本的上述解决方案存在一些问题-建议的插件由于大小写问题而不能完全起作用(nodeName作为属性,有时全部为大写)。因此,我编写了以下快速功能:

$.findNS = function (o, nodeName)
{
    return o.children().filter(function ()
    {
        if (this.nodeName)
            return this.nodeName.toUpperCase() == nodeName.toUpperCase();
        else
            return false;
    });
};

用法示例:

$.findNS($(xml), 'x:row');

考虑到jQuery的版本问题,这显然是最好的解决方案
MatteoSp 2013年

1

内容: $this.find("content\\:encoded, encoded").text()

是完美的解决方案...



0

我还没有看到任何有关使用JQuery解析XML的文档。JQuery通常使用Browser dom浏览HTML文档,我不认为它会读取html本身。

您可能应该看看JavaScript本身内置的XML处理。

http://www.webreference.com/programming/javascript/definitive2/


3
完全不同意。jQuery使处理响应XML变得容易,您将遇到的唯一麻烦是使用xml名称空间。
理查德·克莱顿2009年

1
@Richard:使用Ajax时,jQuery确实使用了responseXML内置XMLHttpRequest对象的属性,该对象的确是XML文档。但是,jQuery(直到1.5parseXML引入时)无法解析XML,因此Chris是正确的。
蒂姆·唐

0

只是用空字符串替换了名称空间。对我来说很好。经过跨浏览器测试的解决方案:Firefox,IE,Chrome

我的任务是通过Sharepoint EXCEL REST API读取和解析EXCEL文件。XML响应包含带有“ x:”名称空间的标签。

我决定用一个空字符串替换XML中的名称空间。以这种方式工作:1.从XML响应中获取感兴趣的节点2.将选定的节点XML响应(文档)转换为字符串2.将名称空间替换为空字符串3.将字符串转换回XML文档

在这里查看代码概述->

function processXMLResponse)(xData)
{
  var xml = TOOLS.convertXMLToString("", "",$(xData).find("entry content")[0]);
  xml = xml.replace(/x:/g, "");            // replace all occurences of namespace
  xData =  TOOLS.createXMLDocument(xml);   // convert string back to XML
}

对于XML到字符串的转换,请在此处找到解决方案:http : //www.sencha.com/forum/showthread.php?34553 -Convert-DOM-XML-Document-to-string


0

另外,您可以在项目中使用fast-xml-parser,然后将XML数据转换为JS / JSON对象。然后,您可以将其用作对象属性。它不使用JQuery或其他库,但可以解决您的目的。

var xmlData = '<xml xmlns:s="uuid:BDC6E3F0-6DA3-11d1-A2A3-00AA00C14882" xmlns:dt="uuid:C2F41010-65B3-11d1-A29F-00AA00C14882" xmlns:rs="urn:schemas-microsoft-com:rowset" xmlns:z="#RowsetSchema">'
+'   <s:Schema id="RowsetSchema">'
+'     <s:ElementType name="row" content="eltOnly" rs:CommandTimeout="30">'
+'       <s:AttributeType name="ows_ID" rs:name="ID" rs:number="1">'
+'        <s:datatype dt:type="i4" dt:maxLength="4" />'
+'      </s:AttributeType>'
+'       <s:AttributeType name="ows_DocIcon" rs:name="Type" rs:number="2">'
+'        <s:datatype dt:type="string" dt:maxLength="512" />'
+'      </s:AttributeType>'
+'       <s:AttributeType name="ows_LinkTitle" rs:name="Title" rs:number="3">'
+'        <s:datatype dt:type="string" dt:maxLength="512" />'
+'      </s:AttributeType>'
+'       <s:AttributeType name="ows_ServiceCategory" rs:name="Service Category" rs:number="4">'
+'        <s:datatype dt:type="string" dt:maxLength="512" />'
+'      </s:AttributeType>'
+'    </s:ElementType>'
+'  </s:Schema>'
+'   <rs:data>'
+'    <z:row ows_ID="2" ows_LinkTitle="Sample Data 1" />'
+'    <z:row ows_ID="3" ows_LinkTitle="Sample Data 2" />'
+'    <z:row ows_ID="4" ows_LinkTitle="Sample Data 3" />'
+'  </rs:data>'
+'</xml>'

var jsObj = parser.parse(xmlData,{attrPrefix:"",ignoreTextNodeAttr: false});
document.write(JSON.stringify(jsObj.xml["rs:data"]["z:row"][0],null,4) + "<br>");
document.write(JSON.stringify(jsObj.xml["rs:data"]["z:row"][1],null,4) + "<br>");
document.write(JSON.stringify(jsObj.xml["rs:data"]["z:row"][2],null,4) + "<br>");
<script src="https://cdnjs.cloudflare.com/ajax/libs/fast-xml-parser/2.9.2/parser.min.js"></script>

您可以在解析js / json对象时忽略名称空间。在这种情况下,您可以直接访问jsObj.xml.data.row

for(var i=0; i< jsObj.xml.data.row.length; i++){
  console.log(jsObj.xml.data.row[i]);
}

免责声明:我已经创建了fast-xml-parser。


-1

对于Webkit浏览器,您可以不用冒号。因此<media:content>,例如,要在RSS feed中查找,可以执行以下操作:

$(this).find("content");

在最新的野生动物园中,它不支持该用法。它仅适用于以前的版本。
巴里·李
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.