无法通过XML中的类属性应用CSS

时间:2012-02-13 15:12:05

标签: javascript jquery html css xml

如果我通过jQuery读取XML,我无法通过class属性将CSS规则应用于包含的元素。

示例:

我有以下XML:

<?xml version="1.0" encoding="UTF-8"?>
<div class="alpha">won't be found by CSS!</div>

我通过AJAX将它加载到我的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'));
        });
      }
    });
});

然后,我有以下CSS:

.alpha {
    color: red;
}

最后,原始HTML看起来像这样(在追加之前):

<div class="alpha">will be found by CSS!</div>
<div id="result"></div>

所以最后,会有两个class=alpha的div。奇迹是CSS将应用于第一个但不是第二个,它来自XML输入。我做错了什么?

1 个答案:

答案 0 :(得分:6)

HTML不是XML。正如Ryan P所说,如果您使用HTML发送回复,最简单的解决方案是将其实际发送为HTML,而不是XML。

但是如果你因任何原因需要在XML响应中发送HTML标记,那么正确的方法就是将HTML放在CDATA部分中,并读取该CDATA部分。以下是修改后的snippet.xml

<?xml version="1.0" encoding="UTF-8"?>
<response>
    <html><![CDATA[<div class="alpha">will also be found by CSS!</div>]]></html>
</response>

然后,使用jQuery的.find()方法检索XML <html>元素,获取其文本,然后将该文本附加到#result。这是修改后的success回调:

success: function(xml) {
  $(xml).find('html').each(function() {
    var html = $(this).text();
    $(html).appendTo($('#result'));
  });
}

使用.appendTo()字符串的html调用将如下所示:

$('<div class="alpha">will also be found by CSS!</div>').appendTo($('#result'));

所以它会起作用,给你这个结果HTML:

<div class="alpha">will be found by CSS!</div>
<div id="result"><div class="alpha">will also be found by CSS!</div></div>

以下是对问题中发生的事情的一些解释,对于任何感兴趣的人(如果您愿意,请将“HTML”替换为“XHTML”):

您的XML <div>元素不是HTML <div>元素;它只是一个XML <div>元素,没有任何语义含义。因此,XML中的class属性根本没有语义含义。

CSS中的类选择器不仅仅通过名为class的属性选择任何元素 - 其选择器将是属性选择器[class~="alpha"],而不是.alpha。类选择器在XML文档中匹配的内容取决于XML命名空间认为的哪个类属性,该属性可能命名为class,也可能不命名。{1}}。 See the spec.

以下是jQuery将您的XML发送回页面时实际生成的内容:

<div class="alpha">will be found by CSS!</div>
<div id="result"><div xmlns="" class="alpha">won't be found by CSS!</div></div>

请注意空白xmlns属性?这就是将第二个div元素转换为一些完全未知的元素,或者我应该说不存在的 XML命名空间(the xmlns attribute cannot be blank,顺便说一下)。

因此,由于第二个div不再是HTML元素,因此CSS中的类选择器将不匹配它,因为它的class属性不再具有正确的语义才能成为匹配(因为没有为此元素定义XML名称空间)。

为什么jQuery的类选择器在这里工作呢?

$(xml).find('div.alpha').each(function() {
  $(this).appendTo($('#result'));
});

这是因为jQuery将XML响应转换为HTML作为DOM对象,然后在DOM对象上执行选择器,这是因为jQuery的类选择器只是要求元素的className。但是,实际附加的内容将附加为XML,而不是HTML。