使用Javascript附加元素可以使用.innerHTML,但不能使用XML子节点

时间:2015-05-12 03:58:07

标签: javascript jquery html xml dom

可能有更简单的方法来做到这一点,但我尝试了一些新的东西。

基本要点是我希望在我的静态网站上每页每页有一个JS和一个jQuery附件。我希望能够将元素附加到身体上,但也可以。我的文件是:

home.html的

<head>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
    <script src="eco.js"></script>
</head>

eco.js

window.addEventListener("load", function() {
    var ajax = new XMLHttpRequest();
    ajax.onload = postdata;
    ajax.open("GET", ADDRESS, true);
    ajax.send();
} );

function postdata() {
    var xml = jQuery.parseXML(this.responseText);
    $("head").append(xml.querySelector("head").childNodes);
}

和common.xml

<head>
    <link href='eco.css' type='text/css' rel='stylesheet' /> 
    <link href='home.css' type='text/css' rel='stylesheet' /> 
</head>

但是,这不起作用(请求并成功检索common.xml)。 Chrome开发工具显示xml节点也成功附加到头部。然而,该页面并未反映出这些变化,特别是css未被纳入。但是,如果我改变

    var xml = jQuery.parseXML(this.responseText);
    $("head").append(xml.querySelector("head").childNodes);

$("head").append(this.responseText);

(并修复common.xml以删除不需要的标签)然后页面反映更改。谁能解释一下这里发生了什么?

谢谢!

1 个答案:

答案 0 :(得分:4)

jQuery.parseXML()返回一个XMLDocument对象,它表示一个通用的XML DOM,它与HTML DOM不兼容。

在将XML文件解析为XML后附加子节点时,最终插入的是XML元素,而不是HTML元素。由于HTML处理器只能理解HTML link元素,因此当它们来自XML DOM时,它们无法识别它们 - 它们会成为未知元素,并且没有其预期意义。

当您直接附加响应标记时,该标记将被解释为HTML,因为您正在直接使用页面中的HTML DOM。这样,您的link元素就可以按预期工作,引用外部样式表以用于您的页面。

以下示例(带有非head元素)演示了如何使用问题中的相同方法在HTML和XML之间区分b元素。在HTML中,它代表text that is meant to stand out from a paragraph,具有关联的默认样式。在纯XML中,它只是一个任意元素,没有默认样式。在Firefox和IE中,每个b元素也正确响应命名空间的CSS选择器(注意它们甚至使用HTML元素使用XHTML命名空间),尽管IE根本不插入XML元素,而是抛出{{{ 1}}。所包含的CSS在Chrome中也不能很好地工作 - 大概是因为,与IE一样,尝试将HTML和XML纠缠在一起并不是最明智的事情。

WrongDocumentError
$(function() {
  var html = '<b>HTML b element</b>';
  var xml = '<root><b>XML b element</b></root>';

  $('p.html').append(html);

  var xmlDoc = jQuery.parseXML(xml);
  $('p.xml').append(xmlDoc.querySelector(':root').childNodes);
});
@namespace 'http://www.w3.org/1999/xhtml';

b::before {
  content: 'Default namespace ';
}

|b::before {
  content: 'Non-namespaced ';
}

/* Any or no namespace */
*|b {
  color: blue;
}

有趣的是,如果你使用<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script> <p class="html"></p> <p class="xml"></p>而不是xml.querySelector("head").innerHTML,它似乎可行,尽管xml.querySelector("head").childNodes对象不是Element(即{ {1}}返回false)。根据{{​​3}},在最新版本的Firefox和Chrome HTMLElement中表示XML元素节点内容的XML序列化,这解释了这种行为。但是,不应该依赖xml.querySelector("head") instanceof HTMLElement这个特殊的怪癖,因为它不是跨浏览器兼容的。

最终,您最好的选择是首先不要将您的文档解析为XML;通过直接附加innerHTML简单地将其视为常规HTML片段,因为jQuery能够处理HTML片段。