使用命名空间进行jQuery XML解析

Bri*_*ang 80 javascript xml jquery xsd namespaces

我是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>
Run Code Online (Sandbox Code Playgroud)

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

到目前为止,我一直在做:

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

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

Bri*_*ang 132

我知道了.

事实证明它需要\\逃脱结肠.

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

正如里奇指出:

更好的解决方案不需要转义并适用于所有"现代"浏览器:

.find("[nodeName=z:row]")
Run Code Online (Sandbox Code Playgroud)

  • 现在jQuery 1.7已经推出,最后一个解决方案不再适用了.什么是新方式? (15认同)
  • 尽管这回答了给定XML文档的问题,但我想提醒人们_prefixes_喜欢`rs`,`dt`或`s`实际上不是命名空间.名称空间是文件顶部的URN.前缀只是文档作者选择的别名,以保持简短.可以使用完全不同的前缀创建匹配相同名称空间的相同文档.我鼓励每个人都寻找理解命名空间的API而不是在查询中假设前缀.例如,在浏览器DOM API中,您可以使用`getElementByTagNameNS()`和`getAttributeNS()`. (4认同)
  • 在jQuery 1.8.x中,它不再起作用了.它应该通过自定义伪类兼容性解决方法来完成,如[here]所述(http://www.h-online.com/open/news/item/jQuery-1-8-1-has-compatibility-workaround-for -custom-伪选择-1696774.html). (3认同)
  • `$('[nodeName = rs:data]',xml).find('[nodeName = z:row]')` - 在WebKit下使用1.3.2(转义冒号方法显然没有) (2认同)
  • 这似乎已停止在jQuery版本1.4.4中工作,我认为这意味着jQuery具有更好的XML命名空间支持.所以为了安全起见,这是`$('[nodeName = rs:data],data')` (2认同)

Fas*_*ani 35

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

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

我正在尝试刮取一个WordPress Feed,其内容名为<content:encoded>,这对我有用:

content: $this.find("content\\:encoded, encoded").text()
Run Code Online (Sandbox Code Playgroud)

  • 这是唯一一个使用最新的jQuery(相同版本)可靠地为我工作的人,谢谢! (3认同)
  • 这对我有用,而我使用`.each()`循环来遍历`item`元素:`$('dc \\:creator,creator',this).text()`.虽然,我不确定为什么需要额外的',创造者',而且'dc \\:creator`不仅仅起作用. (2认同)

小智 20

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

.find('[nodeName="z:row"]')
Run Code Online (Sandbox Code Playgroud)


Ric*_*ich 19

虽然上面的答案似乎是正确的,但它在webkit浏览器(Safari,Chrome)中不起作用.我认为更好的解决方案是:

.find("[nodeName=z:myRow, myRow]")    
Run Code Online (Sandbox Code Playgroud)

  • 这似乎已停止在jQuery版本1.4.4中工作,我认为这意味着jQuery具有更好的XML命名空间支持.所以为了安全起见,这是`$('[nodeName = rs:data],data')` (5认同)

cpr*_*ack 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;
}
Run Code Online (Sandbox Code Playgroud)

如果您需要返回所有匹配元素,可以轻松修改它.希望能帮助到你!


小智 14

上述解决方案都没有那么好用.我发现了这个并且速度有所提高.只需添加这个,就像一个魅力:

$.fn.filterNode = function(name) {
    return this.find('*').filter(function() {
       return this.nodeName === name;
    });
};
Run Code Online (Sandbox Code Playgroud)

用法:

var ineedthatelementwiththepsuedo = $('someparentelement').filterNode('dc:creator');
Run Code Online (Sandbox Code Playgroud)

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


小智 9

"\\"逃脱并非万无一失且简单明了

.find('[nodeName="z:row"]')
Run Code Online (Sandbox Code Playgroud)

从Jquery 1.7开始,方法似乎已被破坏.我能够使用过滤功能找到1.7的解决方案,这里:改进Javascript XML节点查找性能