jQuery XML parsing with namespaces

2018-12-31 09:39发布

I'm new to jQuery and would like to parse an xml document.

I'm able to parse regular XML with the default namespaces but with xml such as:

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

All I really want are the <z:row>'s.

So far, I've been doing:

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

With really no luck. Any ideas? Thanks.

20条回答
何处买醉
2楼-- · 2018-12-31 09:49

In case someone needs to do this without jQuery, just with normal Javascript, and for Google Chrome (webkit), this is the only way I found to get it to work after a lot of research and testing.

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

That will work for retrieving the following node: <prefix:name>. As you can see the prefix or namespace is omitted, and it will match elements with different namespaces provided the tag name is name. But hopefully this won't be a problem for you.

None of this worked for me (I am developping a Google Chrome extension):

getElementsByTagNameNS("prefix", "name")

getElementsByTagName("prefix:name")

getElementsByTagName("prefix\\:name")

getElementsByTagName("name")

Edit: after some sleep, I found a working workaround :) This function returns the first node matching a full nodeName such as <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;
}

It can easily be modified in case you need to return all the matching elements. Hope it helps!

查看更多
低头抚发
3楼-- · 2018-12-31 09:49

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

is the perfect solution...

查看更多
泪湿衣
4楼-- · 2018-12-31 09:49

There is a plugin jquery-xmlns for jQuery to work with namespaces in selectors.

查看更多
人间绝色
5楼-- · 2018-12-31 09:50

As mentioned above, there are problems with the above solution with current browsers/versions of jQuery - the suggested plug-in doesn't completely work either because of case issues (nodeName, as a property, is sometimes in all upper case). So, I wrote the following quick function:

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

Example usage:

$.findNS($(xml), 'x:row');
查看更多
若你有天会懂
6楼-- · 2018-12-31 09:53

None of the solutions above work that well. I found this and has been improved for speed. just add this, worked like a charm:

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

usage:

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

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

查看更多
时光乱了年华
7楼-- · 2018-12-31 09:53

As of beginning of 2016, for me the following syntax works with jQuery 1.12.0:

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

The syntax .find("[nodeName=z:row]") doesn't work in any of the browsers mentioned above. I found no way to apply a namespace in Chrome.

Putting it all together, the following syntax works in all of the browsers mentioned above: .find("row,z\\:row")

查看更多
登录 后发表回答