Attaching <head> elements with Javascript works with .innerHTML, but not with XML child nodes

There are probably easier ways to do this, but I'm trying something new.

The main point is that I want to have one JS and one jQuery app for every page in my static website. I want to be able to add elements to the body, but also the head. My files:

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);
}

      

and common.xml

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

      

However, this does not work (common.xml is requested and retrieved successfully). Chrome dev tools show the xml nodes have been added to the head successfully as well. However, the page does not reflect the changes, especially the CSS is not included. However, if I change

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

      

to

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

      

(and fix common.xml to remove unneeded tags) then the page reflects the changes. Can anyone explain what is going on here?

Thank!

+3


source share


1 answer


jQuery.parseXML()

returns an object XMLDocument

that is a generic XML DOM that is incompatible with the HTML DOM.

When you add child nodes after parsing an XML file in XML format, what you insert are XML elements, not HTML elements. Since the HTML processor only understands HTML elements link

, it does not recognize them when they come from the XML DOM - they become unknown elements and have no intended meaning.

When you add the markup to the responses directly, that markup is interpreted as HTML because you are working directly with the HTML DOM in your page. This allows your link

elements to work as intended by referencing external stylesheets for use with your page.


The following example with an element without a title shows how the element b

differs between HTML and XML using the same techniques in your question. In HTML, it represents text to stand out from a paragraph , with associated default styles. In plain XML, this is just an arbitrary element with no default styles. In Firefox and IE, each element b

also responds correctly to a named CSS selector (note that they use the XHTML namespace even with HTML elements), although IE does not insert the XML element at all, throwing it instead WrongDocumentError

. The included CSS doesn't work very well in Chrome either - presumably because, as with IE, trying to compromise HTML and XML together isn't exactly the right thing to do.



$(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>
      

Interestingly, if you use xml.querySelector("head").innerHTML

rather than xml.querySelector("head").childNodes

, it works even though the object is Element

not HTMLElement

(i.e. it xml.querySelector("head") instanceof HTMLElement

returns false). According to this new answer from Louis , recent versions of Firefox and Chrome innerHTML

introduced XML serialization of the content of the XML node element, which explains this behavior. However, this feature innerHTML

cannot be relied upon as it is not cross-browser compatible.

Ultimately, your best bet is not to parse your document as XML in the first place; just treat it like a normal HTML snippet by adding directly responseText

as jQuery is capable of handling HTML snippets.

+4


source







All Articles