If I read in XML via jQuery, I can’t apply CSS rules to contained elements via their class attributes.
Example:
I have the following XML:
<?xml version="1.0" encoding="UTF-8"?>
<div class="alpha">won't be found by CSS!</div>
I load it via AJAX to my HTML:
$(document).ready(function() {
$.ajax({
url: 'snippet.xml',
type: 'GET',
dataType: 'xml',
timeout: 10000,
error: function() { alert('Error loading XML document'); },
success: function(xml) {
$(xml).find('div.alpha').each(function() {
$(this).appendTo($('#result'));
});
}
});
});
Then, I have the following CSS:
.alpha {
color: red;
}
Finally, the original HTML looks like this (before appending):
<div class="alpha">will be found by CSS!</div>
<div id="result"></div>
So in the end, there will be two divs with class=alpha. The miracle is CSS will be applied to the first one but not the second, which comes from the XML input. What am I doing wrong?
HTML is not XML. As Ryan P said, if you’re sending a response in HTML, the easiest solution is to actually send it as HTML, not XML.
But if you need to send HTML markup in an XML response for whatever reason, the proper way to do it is to put the HTML in a CDATA section, and read that CDATA section. Here’s a modified
snippet.xmlfor example:Then, use jQuery’s
.find()method to retrieve the XML<html>element, get its text, then append that text into#result. Here’s the modifiedsuccesscallback:The
.appendTo()call with thehtmlstring will look like this:So it will work, giving you this resulting HTML:
Here’s some explanation of what’s happening in the question, for anyone interested (substitute “HTML” with “XHTML” if you prefer):
Your XML
<div>element is not an HTML<div>element; it is just an XML<div>element with no semantic meaning whatsoever. Therefore, theclassattribute in your XML has no semantic meaning at all either.The class selector in CSS doesn’t just select any element by an attribute named
class— the selector for that would be the attribute selector[class~="alpha"], not.alpha. What a class selector matches in an XML document depends on whatever the XML namespace considers a class attribute, which may or may not be namedclass. See the spec.Here’s what’s actually generated when jQuery sends your XML back to your page:
Notice the blank
xmlnsattribute? That’s what turns the seconddivelement into an element of some completely unknown, or should I say nonexistent XML namespace (thexmlnsattribute cannot be blank, by the way).So, since the second
divis no longer an HTML element, the class selector in your CSS won’t match it, because itsclassattribute no longer possesses the correct semantics in order to be matched (as there is no XML namespace defined for this element).Why does jQuery’s class selector here work then?
That’s because jQuery converts the XML response to HTML as a DOM object, then executes the selector on the DOM object, which works because jQuery’s class selector just asks for an element’s
className. However, what’s actually appended is appended as XML, not HTML.