jQuery XML与命名空间解析

我是新来的jQuery,并想分析一个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"); 

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

我知道了。

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

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

正如Rich指出的那样:

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

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

我已经花了几个小时阅读关于插件和各种解决方案,没有运气。

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

我试图抓取内容被命名为<content:encoded>的WordPress提要,这对我来说是有效的:

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

如果您正在使用jQuery 1.5,您将不得不围绕节点选择器属性值添加引号以使其工作:

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

虽然上面的答案似乎是正确的,但它不适用于webkit浏览器(Safari,Chrome)。 我相信一个更好的解决方案是:

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

如果有人需要不使用jQuery ,只使用普通的Javascript和谷歌浏览器(webkit)来做到这一点,这是我经过大量的研究和测试后才发现的。

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

这将用于检索以下节点: <prefix:name> 。 正如你所看到的,前缀或名字空间被省略,并且它将匹配具有不同名字空间的元素,只要标签名称是name 。 但是,希望这不会成为你的问题。

这一切都没有为我工作 (我正在开发一个谷歌浏览器扩展):

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

如果您需要返回所有匹配的元素,可以很容易地进行修改。 希望它有帮助!

上述解决方案都没有效果。 我发现这一点,速度已经提高。 只要加上这个,就像一个魅力:

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

“\\”逃避不是万无一失的简单

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

方法似乎已经打破了Jquery 1.7。 我能找到1.7的解决方案,使用过滤器功能,在这里: 提高Javascript XML节点寻找性能

值得注意的是,从jQuery 1.7开始,在寻找命名空间元素方面存在一些问题。 请参阅以下链接了解更多信息:

  • jQuery Bug Ticket注意到缺少跨浏览器支持的能力.find('[nodeName =“z:row”]')
  • 建议使用一些性能测试的插件解决方法。

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

在冒号为我工作之后使用节点名称的后半部分。 使用.find(“lat”)而不是.find(“geo \:lat”) ,它为我工作。


我的设置:

  • Chrome 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")); 

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

jQuery 1.7不适用于以下内容:

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

我曾经在Chrome,Firefox和IE中使用过的一个解决方案是使用选择器,这个选择器可以在IE和Chrome中运行,

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

在IE中,这将返回使用名称空间(Firefox和IE需要名称空间)的节点,而在Chrome中,选择器将基于非名称空间选择器返回节点。 我没有在Safari中测试过,但它应该可以工作,因为它在Chrome中工作。

我的解决方案(因为我使用一个PHP代理)是用_替换:命名空间,所以没有更多的命名空间问题;-)

把事情简单化 !

原始答案: jQuery XML解析如何获取元素属性

以下是如何成功获取Chrome中的值的示例

  item.description = jQuery(this).find("[nodeName=itunes\\:summary]").eq(0).text(); 

如上所述,使用当前浏览器/ 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'); 

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

是完美的解决方案…

截至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")

有一个插件jquery-xmlns让jQuery能够在选择器中使用命名空间。

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

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

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

只是用空字符串替换了命名空间。 为我工作得很好。 跨浏览器测试的解决方案:Firefox,IE,Chrome

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

我决定用空字符串替换XML中的名称空间。 以这种方式工作:1.从XML响应中获取感兴趣的节点2.将所选节点XML-Response(Document)转换为字符串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

对于Webkit浏览器,您可以忽略冒号。 所以要找到RSS feed中的<media:content> ,你可以这样做:

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