Skip to main content

Bug Tracker

Side navigation

#155 closed enhancement ()

Opened August 30, 2006 05:08AM UTC

Closed November 11, 2010 11:09PM UTC

Last modified October 30, 2012 05:33AM UTC

Get Namespaced Elements in XML Documents

Reported by: slantedtiles@gmail.com Owned by: slantedtiles@gmail.com
Priority: low Milestone: 1.5
Component: core Version: 1.2.2
Keywords: xml namespaces Cc:
Blocked by: Blocking:
Description

I've recently had the need to improve jQuery's selector support for XML

nodes with prefixes. In theory, it should be possible for a node with

the node name "D:response" to be selected using just "response", in

accordance with getElementsByTagName's rules. There's two issues that

prevent that, which I've included fixes for.

The first is that IE supports getElementsByTagName incorrectly, and

treats prefixes as part of the tag name. Using rev 234, lines 1228-1233

could be replaced with this:

for ( var i = 0; i < ret.length; i++ ) {
  // create an array of tagnames to search for
  var tags = {};

  // fix for IE leaving in node prefixes
  if (jQuery.browser.msie && ret[i].xml !== undefined && m[2] != '*')
    for (var regex = new RegExp('</?((?:[^:]+:)?' + m[2] + ')\\b', 'g'), tag;
      (tag = regex.exec(ret[i].xml)) != null; tags[tag[1]] = true);
  else tags[m[2]] = true;

  for ( var tag in tags )
    r = jQuery.merge( r, tag == "*" ?
      jQuery.getAll(ret[i]) :
       ret[i].getElementsByTagName(tag));
}

If it detects that we're searching an XML document and IE is being used,

it'll find all node names with the correct local name, get their

complete node names with prefixes, and search for each of those in turn.

If IE is not being used or we're searching an HTML document, it'll

search only for the specified tag name, so the overhead seems rather

minimal.

The second issue is that jQuery prevents nodes with prefixes from being

preserved in the filter function, specifically because of line 1014:

"": "m[2]== '*'||a.nodeName.toUpperCase()==m[2].toUpperCase()",

Which could be replaced with:

"": "m[2]== '*'||a.nodeName.replace(/[^:]+:/,
'').toUpperCase()==m[2].toUpperCase()";

That'll make sure only the local name is being compared instead of the

complete node name. (The best solution would be to use a.localName, but

IE doesn't support it, of course...)

If you could look this over and send a reply, I'd be very grateful.

— Mitchell Lane

PS: The next step to this would be adding support for a namespace

resolver, perhaps as a third parameter of $() and by using the CSS

syntax ("D|response"). Would you have any interest if I were to try and

write support for that?

Attachments (0)
Change History (11)

Changed November 17, 2006 09:48PM UTC by john comment:1

description: I've recently had the need to improve jQuery's selector support for XML\ nodes with prefixes. In theory, it should be possible for a node with\ the node name "D:response" to be selected using just "response", in\ accordance with getElementsByTagName's rules. There's two issues that\ prevent that, which I've included fixes for.\ \ The first is that IE supports getElementsByTagName incorrectly, and\ treats prefixes as part of the tag name. Using rev 234, lines 1228-1233\ could be replaced with this:\ \ for ( var i = 0; i < ret.length; i++ ) {\ // create an array of tagnames to search for\ var tags = {};\ // fix for IE leaving in node prefixes\ if (jQuery.browser.msie && ret[i].xml !== undefined && m[2] != '*')\ for (var regex = new RegExp('</?((?:[^:]+:)?' + m[2] + ')\\b', 'g'), tag;\ (tag = regex.exec(ret[i].xml)) != null; tags[tag[1]] = true);\ else tags[m[2]] = true;\ \ for ( var tag in tags )\ r = jQuery.merge( r,\ tag == "*" ?\ jQuery.getAll(ret[i]) :\ ret[i].getElementsByTagName(tag)\ );\ }\ \ If it detects that we're searching an XML document and IE is being used,\ it'll find all node names with the correct local name, get their\ complete node names with prefixes, and search for each of those in turn.\ If IE is not being used or we're searching an HTML document, it'll\ search only for the specified tag name, so the overhead seems rather\ minimal.\ \ The second issue is that jQuery prevents nodes with prefixes from being\ preserved in the filter function, specifically because of line 1014:\ \ "": "m[2]== '*'||a.nodeName.toUpperCase()==m[2].toUpperCase()",\ \ Which could be replaced with:\ \ "": "m[2]== '*'||a.nodeName.replace(/[^:]+:/,\ '').toUpperCase()==m[2].toUpperCase()";\ \ That'll make sure only the local name is being compared instead of the\ complete node name. (The best solution would be to use a.localName, but\ IE doesn't support it, of course...)\ \ If you could look this over and send a reply, I'd be very grateful.\ \ — Mitchell Lane\ \ PS: The next step to this would be adding support for a namespace\ resolver, perhaps as a third parameter of $() and by using the CSS\ syntax ("D|response"). Would you have any interest if I were to try and\ write support for that?I've recently had the need to improve jQuery's selector support for XML\ nodes with prefixes. In theory, it should be possible for a node with\ the node name "D:response" to be selected using just "response", in\ accordance with getElementsByTagName's rules. There's two issues that\ prevent that, which I've included fixes for.\ \ The first is that IE supports getElementsByTagName incorrectly, and\ treats prefixes as part of the tag name. Using rev 234, lines 1228-1233\ could be replaced with this:\ {{{\ for ( var i = 0; i < ret.length; i++ ) {\ // create an array of tagnames to search for\ var tags = {};\ \ // fix for IE leaving in node prefixes\ if (jQuery.browser.msie && ret[i].xml !== undefined && m[2] != '*')\ for (var regex = new RegExp('</?((?:[^:]+:)?' + m[2] + ')\\b', 'g'), tag;\ (tag = regex.exec(ret[i].xml)) != null; tags[tag[1]] = true);\ else tags[m[2]] = true;\ \ for ( var tag in tags )\ r = jQuery.merge( r, tag == "*" ?\ jQuery.getAll(ret[i]) :\ ret[i].getElementsByTagName(tag));\ }\ }}}\ \ If it detects that we're searching an XML document and IE is being used,\ it'll find all node names with the correct local name, get their\ complete node names with prefixes, and search for each of those in turn.\ If IE is not being used or we're searching an HTML document, it'll\ search only for the specified tag name, so the overhead seems rather\ minimal.\ \ The second issue is that jQuery prevents nodes with prefixes from being\ preserved in the filter function, specifically because of line 1014:\ \ {{{\ "": "m[2]== '*'||a.nodeName.toUpperCase()==m[2].toUpperCase()",\ }}}\ \ Which could be replaced with:\ \ {{{\ "": "m[2]== '*'||a.nodeName.replace(/[^:]+:/,\ '').toUpperCase()==m[2].toUpperCase()";\ }}}\ \ That'll make sure only the local name is being compared instead of the\ complete node name. (The best solution would be to use a.localName, but\ IE doesn't support it, of course...)\ \ If you could look this over and send a reply, I'd be very grateful.\ \ — Mitchell Lane\ \ PS: The next step to this would be adding support for a namespace\ resolver, perhaps as a third parameter of $() and by using the CSS\ syntax ("D|response"). Would you have any interest if I were to try and\ write support for that?
priority: majorminor

Changed October 18, 2007 12:49PM UTC by Orange comment:2

Is there any improvement on that point planned ?

In jQuery-1.2.1.js, it's only two changes to add on lines :

 1260 : c.nodeName.replace(/^.*:/,'').toUpperCase() 
instead of
 c.nodeName.toUpperCase() 
 1284 : n.nodeName.replace(/^.*:/,'').toUpperCase() 
instead of
 n.nodeName.toUpperCase() 

Hope this will be implemented as it blocks the use of jQuery with namespaced XMLs.

Orange

Changed January 14, 2008 10:46PM UTC by george.petro comment:3

any status on this one? Seems still not implemented...

Changed April 03, 2008 03:20PM UTC by mihxil comment:4

Can I vote for this bug to be fixed?

Changed May 12, 2008 12:49AM UTC by flesler comment:5

description: I've recently had the need to improve jQuery's selector support for XML\ nodes with prefixes. In theory, it should be possible for a node with\ the node name "D:response" to be selected using just "response", in\ accordance with getElementsByTagName's rules. There's two issues that\ prevent that, which I've included fixes for.\ \ The first is that IE supports getElementsByTagName incorrectly, and\ treats prefixes as part of the tag name. Using rev 234, lines 1228-1233\ could be replaced with this:\ {{{\ for ( var i = 0; i < ret.length; i++ ) {\ // create an array of tagnames to search for\ var tags = {};\ \ // fix for IE leaving in node prefixes\ if (jQuery.browser.msie && ret[i].xml !== undefined && m[2] != '*')\ for (var regex = new RegExp('</?((?:[^:]+:)?' + m[2] + ')\\b', 'g'), tag;\ (tag = regex.exec(ret[i].xml)) != null; tags[tag[1]] = true);\ else tags[m[2]] = true;\ \ for ( var tag in tags )\ r = jQuery.merge( r, tag == "*" ?\ jQuery.getAll(ret[i]) :\ ret[i].getElementsByTagName(tag));\ }\ }}}\ \ If it detects that we're searching an XML document and IE is being used,\ it'll find all node names with the correct local name, get their\ complete node names with prefixes, and search for each of those in turn.\ If IE is not being used or we're searching an HTML document, it'll\ search only for the specified tag name, so the overhead seems rather\ minimal.\ \ The second issue is that jQuery prevents nodes with prefixes from being\ preserved in the filter function, specifically because of line 1014:\ \ {{{\ "": "m[2]== '*'||a.nodeName.toUpperCase()==m[2].toUpperCase()",\ }}}\ \ Which could be replaced with:\ \ {{{\ "": "m[2]== '*'||a.nodeName.replace(/[^:]+:/,\ '').toUpperCase()==m[2].toUpperCase()";\ }}}\ \ That'll make sure only the local name is being compared instead of the\ complete node name. (The best solution would be to use a.localName, but\ IE doesn't support it, of course...)\ \ If you could look this over and send a reply, I'd be very grateful.\ \ — Mitchell Lane\ \ PS: The next step to this would be adding support for a namespace\ resolver, perhaps as a third parameter of $() and by using the CSS\ syntax ("D|response"). Would you have any interest if I were to try and\ write support for that?I've recently had the need to improve jQuery's selector support for XML \ nodes with prefixes. In theory, it should be possible for a node with \ the node name "D:response" to be selected using just "response", in \ accordance with getElementsByTagName's rules. There's two issues that \ prevent that, which I've included fixes for. \ \ The first is that IE supports getElementsByTagName incorrectly, and \ treats prefixes as part of the tag name. Using rev 234, lines 1228-1233 \ could be replaced with this: \ {{{ \ for ( var i = 0; i < ret.length; i++ ) { \ // create an array of tagnames to search for \ var tags = {}; \ \ // fix for IE leaving in node prefixes \ if (jQuery.browser.msie && ret[i].xml !== undefined && m[2] != '*') \ for (var regex = new RegExp('</?((?:[^:]+:)?' + m[2] + ')\\b', 'g'), tag; \ (tag = regex.exec(ret[i].xml)) != null; tags[tag[1]] = true); \ else tags[m[2]] = true; \ \ for ( var tag in tags ) \ r = jQuery.merge( r, tag == "*" ? \ jQuery.getAll(ret[i]) : \ ret[i].getElementsByTagName(tag)); \ } \ }}} \ \ If it detects that we're searching an XML document and IE is being used, \ it'll find all node names with the correct local name, get their \ complete node names with prefixes, and search for each of those in turn. \ If IE is not being used or we're searching an HTML document, it'll \ search only for the specified tag name, so the overhead seems rather \ minimal. \ \ The second issue is that jQuery prevents nodes with prefixes from being \ preserved in the filter function, specifically because of line 1014: \ \ {{{ \ "": "m[2]== '*'||a.nodeName.toUpperCase()==m[2].toUpperCase()", \ }}} \ \ Which could be replaced with: \ \ {{{ \ "": "m[2]== '*'||a.nodeName.replace(/[^:]+:/, \ '').toUpperCase()==m[2].toUpperCase()"; \ }}} \ \ That'll make sure only the local name is being compared instead of the \ complete node name. (The best solution would be to use a.localName, but \ IE doesn't support it, of course...) \ \ If you could look this over and send a reply, I'd be very grateful. \ \ — Mitchell Lane \ \ PS: The next step to this would be adding support for a namespace \ resolver, perhaps as a third parameter of $() and by using the CSS \ syntax ("D|response"). Would you have any interest if I were to try and \ write support for that?
need: → Review

What about supporting $('b\\:foo') like with attribute selectors ?

This could just handled with a plugin with something like:

$.nsTag = function( name ){

return $(document.getElementsByTagName(name));

};

$.nsTag('b:foo')... (any jQuery method)

Changed May 16, 2008 02:39AM UTC by flesler comment:6

milestone: → 1.2.4

Changed August 27, 2008 06:22PM UTC by timothy.davi comment:7

This seems to not have made it into 1.2.4 http://dev.jquery.com/report/27. Can you update when this will be fixed?

$(xml).find('ns:elementName').text() would be nice

Changed October 21, 2010 06:02PM UTC by SlexAxton comment:8

keywords: → xml namespaces
milestone: 1.2.41.5
owner: → slantedtiles@gmail.com
priority: minorlow
reporter: slantedtiles@gmail.cslantedtiles@gmail.com
status: newpending
version: → 1.2.2

It's been 2 years and 3 spam messages since anyone checked in on this, anyone still care?

Changed November 11, 2010 11:09PM UTC by trac-o-bot comment:9

status: pendingclosed

Automatically closed due to 14 days of inactivity.

Changed October 11, 2011 06:03AM UTC by JP comment:10

This is still an issue as of 1.4.2, not sure about 1.6.x

Changed October 30, 2012 05:33AM UTC by jhbrock@ics.uci.edu comment:11

This is still broken as of 1.8.2. There's mutually incompatible behavior between browsers:

In Firefox, selectors must include the namespace and escape the colon with two slashes, e.g., you would select <ns:foo> with $(data).find("ns\\\\:foo"). However, this doesn't work in Chrome.

In Chrome, selectors must have the namespace dropped, e.g., you would select <ns:foo> with $(data).find("foo"). However, this doesn't work in Firefox.