如何使用 jQuery 进行带有命名空间的 XML 解析

IT技术 javascript jquery xml namespaces xsd
2021-01-15 12:28:21

我是 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");

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

6个回答

我知道了。

事实证明,它需要\\逃避冒号。

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

正如里奇指出的那样:

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

.find("[nodeName=z:row]")
$('[nodeName=rs:data]', xml).find('[nodeName=z:row]') - 适用于 WebKit 下的 1.3.2(其中转义冒号方法显然没有)
2021-03-16 12:28:21
尽管这回答了给定 XML 文档的问题,但我想提醒人们,前缀之类的rs, dtors实际上不是名称空间。命名空间是文件顶部的 URN。前缀只是文档作者为保持简短而选择的别名。可以使用完全不同的前缀创建匹配相同名称空间的相同文档。我鼓励每个人寻找理解命名空间的 API,而不是在您的查询中假设前缀。例如,在浏览器 DOM API 中,您可以使用getElementByTagNameNS()getAttributeNS()
2021-04-01 12:28:21
现在 jQuery 1.7 已经发布,最后一个解决方案不再适用。新方法是什么?
2021-04-03 12:28:21
这似乎在 jQuery 1.4.4 版中停止工作,我认为这意味着 jQuery 具有更好的 XML 命名空间支持。所以为了安全起见,这是有效的$('[nodeName=rs:data],data')
2021-04-06 12:28:21
在 jQuery 1.8.x 中它不再起作用了。它应该有一个自定义的伪类兼容性的解决方法来实现,如解释在这里
2021-04-08 12:28:21

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

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()
当我使用.each()循环遍历item元素时,这对我有用$('dc\\:creator, creator', this).text(). 虽然,我不确定为什么, creator需要额外的东西,而且dc\\:creator不只是工作。
2021-04-05 12:28:21
这是唯一一个使用最新的 jQuery(相同版本)可靠地为我工作的方法,谢谢!
2021-04-10 12:28:21

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

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

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

.find("[nodeName=z:myRow, myRow]")    
这似乎在 jQuery 1.4.4 版中停止工作,我认为这意味着 jQuery 具有更好的 XML 命名空间支持。所以为了安全起见,这是有效的$('[nodeName=rs:data],data')
2021-04-05 12:28:21

如果有人需要在没有 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;
}

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

我的理解是第一个参数getElementsByTagNameNS()应该是命名空间,而不是前缀。所以是xmlns:prefix根元素上的属性
2021-03-20 12:28:21