views:

618

answers:

4

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.org/2005/Atom"&gt;
    <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.org/2005/Atom"&gt;&lt;atom:x&gt;Text&lt;/atom:x&gt;&lt;/xml&gt;');

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:

  1. What are the alternative work-arounds for this problem? Any better than the one I have found?
  2. Is this a bug in Opera? If yes, which standard says so?

Hope you can help :)

+1  A: 

I think you should say "atom:x" (without the backslashes), and be sure to have the xmlns:atom="http://www.w3.org/2005/Atom" declaration either on the html tag on the main html file, or in some other way known for the javascript.

Rasmus Kaj
That will *not* work. the colon is a special character in jquery and must be escaped.
Kevin Peno
A: 

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.org/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 comment, 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.

Kevin Peno
Thanks for the tips. Unfortunately, I won't be able to test it right away... I will come back to you.
Magnus Hoff
+1  A: 

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

Miguel Ventura
+3  A: 

It'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.org/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.org/2005/Atom namespace.

porneL