Bug Tracker

Opened 12 years ago

Closed 9 years ago

Last modified 7 years ago

#1826 closed feature (wontfix)

namespaces handling for XMLs

Reported by: Orange Owned by:
Priority: minor Milestone:
Component: core Version: 1.2.1
Keywords: Cc:
Blocked by: Blocking:

Description

Actual jQuery does return wrong results as soon as the user uses namespaces in an xml, because IE does not handle namespaces the same way as other browsers does.

In jQuery, this concerns the use of "nodeName" which returns "prefix:tagName" instead of "tagName". This concerns the following lines in jQuery-1.2.1.js which should be corrected with the following, in order to hide namespaces :

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

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

An other element that causes wrong behavior is "getElementsByTagName" which has to be used in IE with "prefix:tagName". This could be corrected by the following change :

line 1362: r = jQuery.merge( r, ret[i].getElementsByTagName( tag )); should be changed in :

// getElementsByTagName will not work with IE & namespaces
var retour = [];
if (jQuery.browser.msie && (ret[i].namespaces!=null) && (ret[i].namespaces.length>0)) {
	retour = jQuery.merge(retour,ret[i].getElementsByTagName(tag));
	for(var nsIndex = 0; nsIndex<ret[i].namespaces.length; nsIndex++) {
		var ns = "xmlns:ns='"+ret[i].namespaces(nsIndex)+"'";
		ret[i].setProperty("SelectionNamespaces", ns);
		var IeReturn = ret[i].selectNodes("ns:"+tag);
		retour = jQuery.merge(retour, IeReturn);
	}
} else {
	retour = ret[i].getElementsByTagName(tag);
}
r = jQuery.merge(r, retour);

Changes have been tested on IE6/7, Mozilla, Safari & Opera. They may be easier way to perform it, but this one works.

Change History (8)

comment:1 Changed 12 years ago by Orange

Error in suggested solution for line 1362 :

var IeReturn = ret[i].selectNodes("ns:"+tag); should be var IeReturn = ret[i].selectNodes("//ns:"+tag);

comment:2 Changed 12 years ago by IvanTheBeara

This is similar to the solution suggested in ticket 155 but this avoids the potentially slow string searching that does with regular expressions. However, his only works when the context is the document node (IXMLDocument2). If the context is a node from within the document (IXMLDOMElement) then this fails because IXMLDOMElement does not have a namespaces property. In addition, the XPath used in selectNodes returns all matching nodes in the document rather than descendants of the context node.

To get around these issues you need to look at the ownerDocument and tweak the XPath. Something like this:

// getElementsByTagName will not work with IE & namespaces
var tags = [];
if (jQuery.browser.msie && ret[i].xml !== undefined && tag != '*') {
	var od = (ret[i].ownerDocument) ? ret[i].ownerDocument : ret[i];
	var ns = od.namespaces;
	if ((ns!=null) && (ns.length>0)) {
		for (var nsIndex = 0; nsIndex<ns.length; nsIndex++) {
			od.setProperty("SelectionNamespaces", "xmlns:ns='" + ns(nsIndex) + "'");
			var IeReturn = ret[i].selectNodes(".//ns:"+tag);
			tags = jQuery.merge(tags, IeReturn);
		}
	}
}
tags = jQuery.merge(tags,ret[i].getElementsByTagName(tag));
r = jQuery.merge(r, tags);

This is really only a partial solution to the issue. What's really needed is a way to specify a namespace in the selector. I've seen a suggestion that the | character be used for that. So, "ns|tag" would return all tags of the form <ns:tag>. But the prefix should not be hard coded in a selector. The whole point of it is that the prefix should be able to be changed to avoid conflicts without affecting code that processes the document.

So, either we include the whole namespace URL in the selector, or we have a way to map another namespace prefix to the URI:

.find(selector, context, nsPrefix, nsURI)

(for example)

comment:3 Changed 12 years ago by IvanTheBeara

And, while I think of it, the first two fixes (adding the replace to the nodeName comparisons in the section that handles child selectors) more-or-less get the job done, but they also have a problem. XML is case sensitive. Converting everything to uppercase to do a comparison might be appropriate for HTML documents but not for XML documents.

comment:4 Changed 9 years ago by dmethvin

#2901 is a duplicate of this ticket.

comment:5 Changed 9 years ago by dmethvin

Status: newopen

This ticket has been open for so long because it appears to be very difficult to solve.

https://bugzilla.mozilla.org/show_bug.cgi?id=414612

For XML docs we'd need to use getElementsByTagNameNS according to that.

Also, Sizzle's first resort of querySelectorAll doesn't support namespaces but it should throw an exception:

http://www.w3.org/TR/selectors-api/#resolving-namespaces

comment:6 Changed 9 years ago by dmethvin

#3404 is a duplicate of this ticket.

comment:7 Changed 9 years ago by john

Milestone: 1.2.2
Resolution: wontfix
Status: openclosed

Honestly, I don't think that this is something that we're going to ever implement. Especially considering that at this point we don't even use querySelectorAll on XML documents. Sorry!

comment:8 Changed 7 years ago by dmethvin

#12787 is a duplicate of this ticket.

Note: See TracTickets for help on using tickets.