Consider this:
<!DOCTYPE HTML>
<html><head><title>XML-problem</title>
<script src="jquery-1.3.2.min.js" type="text/javascript"></script>
<script type="text/javascript">
$(function() {
$('<p/>').load("text.xml", function(responseText, textStatus, xhr) {
var xml = $(xhr.responseXML);
var x_txt = xml.find('atom\\:x').text();
$(this).text(x_txt).appendTo('#container');
});
});
</script>
</head><body><div id="container" /></body></html>
This script should load text.xml when the document has been loaded. text.xml looks like this:
<xml xmlns:atom="">
<atom:x>Text</atom:x>
</xml>
When this file has been loaded, the text contents of the atom:x
-node are appended to the document. I can see "Text" in my browser window.
This works as expected in Firefox. However, it does not work in Opera unless I change the query from 'atom\\:x'
to just 'x'
. In this case it works in Opera, but not Firefox.
I have discovered a workaround, namely changing the query to 'atom\\:x, x'
, but I would rather like to get to the bottom of this.
Now for the funny twist: I can inline the xml directly instead of getting it from XHR by changing
var xml = $(xhr.responseXML);
into
var xml = $('<xml xmlns:atom=""><atom:x>Text</atom:x></xml>');
In this case a query of 'atom\\:x'
will give the desired result in both browsers and just 'x'
will give no result in both browsers.
The fact that this works differently in Opera leads me to conclude that the former behavior is a bug in Opera. Is this a reasonable conclusion? Where can I point to for the standard that describes how this is supposed to work?
In conclusion:
- What are the alternative work-arounds for this problem? Any better than the one I have found?
- Is this a bug in Opera? If yes, which standard says so?
Hope you can help :)
Consider this:
<!DOCTYPE HTML>
<html><head><title>XML-problem</title>
<script src="jquery-1.3.2.min.js" type="text/javascript"></script>
<script type="text/javascript">
$(function() {
$('<p/>').load("text.xml", function(responseText, textStatus, xhr) {
var xml = $(xhr.responseXML);
var x_txt = xml.find('atom\\:x').text();
$(this).text(x_txt).appendTo('#container');
});
});
</script>
</head><body><div id="container" /></body></html>
This script should load text.xml when the document has been loaded. text.xml looks like this:
<xml xmlns:atom="http://www.w3/2005/Atom">
<atom:x>Text</atom:x>
</xml>
When this file has been loaded, the text contents of the atom:x
-node are appended to the document. I can see "Text" in my browser window.
This works as expected in Firefox. However, it does not work in Opera unless I change the query from 'atom\\:x'
to just 'x'
. In this case it works in Opera, but not Firefox.
I have discovered a workaround, namely changing the query to 'atom\\:x, x'
, but I would rather like to get to the bottom of this.
Now for the funny twist: I can inline the xml directly instead of getting it from XHR by changing
var xml = $(xhr.responseXML);
into
var xml = $('<xml xmlns:atom="http://www.w3/2005/Atom"><atom:x>Text</atom:x></xml>');
In this case a query of 'atom\\:x'
will give the desired result in both browsers and just 'x'
will give no result in both browsers.
The fact that this works differently in Opera leads me to conclude that the former behavior is a bug in Opera. Is this a reasonable conclusion? Where can I point to for the standard that describes how this is supposed to work?
In conclusion:
- What are the alternative work-arounds for this problem? Any better than the one I have found?
- Is this a bug in Opera? If yes, which standard says so?
Hope you can help :)
Share Improve this question edited Nov 5, 2009 at 15:33 Jason Berkan 8,9147 gold badges31 silver badges39 bronze badges asked Oct 21, 2009 at 15:25 Magnus HoffMagnus Hoff 22.1k10 gold badges66 silver badges84 bronze badges 9- 2 Looks like a noted bug. thompson-web.blogspot./2009/03/… dev.jquery./ticket/155 – Stefan Kendall Commented Oct 21, 2009 at 15:28
- 1 @Stefan: So, jQuery should give me results when just querying for 'x', no matter the browser? – Magnus Hoff Commented Oct 21, 2009 at 15:35
-
Why are you using
load
? Load should be for html, not xml. Does it work withajax
orget
? – Kobi Commented Oct 21, 2009 at 17:47 -
I actually use
ajax
in the real application. I choseload
for this example to make it smaller. Anyway, it doesn't make any difference in the observed behaviour. – Magnus Hoff Commented Oct 21, 2009 at 19:18 - 3 @brianpeiris: I see that you serve the XML document as text/html. IIRC, this causes XHR to treat it as text, not XML. This is probably the cause of the difference between our two setups. – Magnus Hoff Commented Oct 28, 2009 at 18:03
4 Answers
Reset to default 3It's not a bug in Opera. It's the correct behavior:
In a namespace-aware client, the name part of element type selectors (the part after the namespace separator, if it is present) will only match against the local part of the element's qualified name.
In your case local name is x
, and atom:x
isn't even a legal local name in XML.
Moreover, namespace-prefixed type selector in CSS has different syntax that doesn't use colon at all:
@namespace atom url(http://www.w3/2005/Atom);
atom|x { color: blue }
Your syntax seems to rely on a quirk introduced by HTML parsers in namespace-unaware user-agents.
HTML parser "eats" the colon as part of tag name and you get atom:x
element in default namespace, which would match atom\:x
selector, but in XML that you get x
element in http://www.w3/2005/Atom
namespace.
I've already experienced this behavior in different versions of the same browser and as far as I remember at the time I was testing the problematic page with FF and IE, so I'd say it's not an Opera-specific bug.
I'd suggest that whenever you use jQuery for parsing XML tags with namespace prefixes, you query for the selector both with and without the prefix. That is, instead of using
var x_txt = xml.find('atom\\:x').text();
try
var x_txt = xml.find('atom\\:x, x').text();
I think this is an acceptable workaround for most situations and it will assure that your results are correct despite the misbehaviors...
I think you should say "atom:x" (without the backslashes), and be sure to have the xmlns:atom="http://www.w3/2005/Atom" declaration either on the html tag on the main html file, or in some other way known for the javascript.
It is hard to say if this is a bug in opera or if this is a bug in jQuery that is Opera specific. From the sounds of it, Opera is not properly adding the namespace to the xhr document dom and this is why jQuery cannot query atom:x and also explains why, when you create your own jquery node, you do not get the same results.
First thing I would do is to try and see if atom is a defined namspace in the xhr dom. It should return your atom ns as defined, If not, this is probably an opera bug. I'm not sure the best way to test this, but perhaps: xhr.getElementByTagNameNS( "x" "http://www.w3/2005/Atom" );
will work.
Failing that, Opera claims to support XML namespaces fully however so, I would open a bug request with jQuery and see where that get's you.
In other points, as I eluded to in my ment, I do not think that querying atom:x
by x
is a good idea at all. You may as well not use namespaces since it defeats the purpose.