Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Difference in jQuery with XML namespace and xhr.responseXML between Opera and Firefox

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

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

like image 754
Magnus Hoff Avatar asked Oct 21 '09 15:10

Magnus Hoff


2 Answers

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.

like image 114
Kornel Avatar answered Sep 30 '22 17:09

Kornel


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

like image 39
Miguel Ventura Avatar answered Sep 30 '22 15:09

Miguel Ventura