Bug Tracker

Ticket #8972 (closed bug: invalid)

Opened 4 years ago

Last modified 2 years ago

HIERARCHY_REQUEST_ERROR(3) appending XHTML DIV into XHTML DIV on IE

Reported by: jaraco Owned by: jaraco
Priority: low Milestone: 1.next
Component: ajax Version: 1.5.2
Keywords: xhtml Cc:
Blocking: Blocked by:

Description

I originally created  this post in the forums to better understand why I was unable to load an XHTML document element into another XHTML document node using jQuery 1.5.2 on IE. I've since concluded that to the best of my understanding, jQuery doesn't support loading an XHTML node into another XHTML document unless the new node is coerced into HTML (such as through the 'html' parameter to get).

It should be possible to load an XHTML document that has XML headers on it (such as a <!DOCTYPE> or preprocessing instruction) and add it (or a subnode) to another XHTML document. The following describes a simple example to reproduce the error.

Here's a harness with a script that performs a dynamic load of an XHTML file:

<!DOCTYPE html 
     PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
     "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.5.2/jquery.js" type="text/javascript"></script>
  <script type="text/javascript">
function load_stuff(widget_source, status, request) {
    var node = $(widget_source.documentElement).clone();
    var target = $('#main_cont');
    target.append(node);
}

// Load and init the widget
$(document).ready(function() {$.get('widget.xhtml', load_stuff);});
  </script>
</head>
<body>

  <div id="main_cont">
  </div>

</body>
</html>

And widget.xhtml that it tries to load:

<!DOCTYPE html 
     PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
     "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<div xmlns="http://www.w3.org/1999/xhtml" xmlns:other="http://example.com/other">
  <other:foo />
  Got it!
</div>

The code works on Firefox 4 and Chrome, displaying "Got it!" in the document. On IE, however, it fails with the HIERARCHY_REQUEST_ERROR(3) during the .append call.

As I mentioned in the forum, I can make it work if I remove the <!DOCTYPE> and force HTML processing by passing 'html' to the .get call and remove the reference to 'documentElement'.

Change History

comment:1 Changed 4 years ago by jaraco

The examples as described above will be  hosted here for some time.

comment:2 Changed 4 years ago by timmywil

  • Priority changed from undecided to low
  • Resolution set to duplicate
  • Status changed from new to closed
  • Component changed from unfiled to ajax

comment:3 Changed 4 years ago by timmywil

Duplicate of #8941.

comment:4 Changed 4 years ago by jaraco

These are not duplicate tickets. They describe different errors and invoke different functions. In particular, in this ticket describes using the .get method, which can load XML, and the error occurs when the content is loaded as XML. Furthermore, the resolution for #8941 does not resolve this issue.

In particular, there appears to be no way to load widget.xhtml as given above. It is valid XHTML, but cannot be loaded into the DOM using IE. The only way to make it work is to alter the content server side.

Please re-open this ticket, or close it as "won't fix" and give a reason why this use-case is invalid.

comment:5 Changed 4 years ago by timmywil

You are using the same functions: ajax and domManip (which are the lower level functions for load/get and append/html respectively). And that is not valid XHTML. A div cannot have the xmlns attribute, cannot be placed outside of a body, and the other:foo element is undefined because you're in strict mode.

comment:6 Changed 4 years ago by jaraco

You're right. My mistake. The XHTML doesn't conform strictly to XHTML.

I get the same error if widget.xhtml is this code:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html 
     PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
     "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
  <title>A title</title>
</head>
<body>
<div>
  Got it!
</div>
</body>
</html>

I've updated the widgets.xhtml file and  validated it at w3c. As a result of the change in structure, I've also updated harness.xhtml to get the correct node from the XHTML with

var node = $(widget_source).find('body div').clone();

I get the same error with the strictly-conforming XHTML file. This is because node is still an IXMLDomDocument2 and can't be appended to another div.

What's the proper way to load an XHTML document into another?

comment:7 follow-up: ↓ 10 Changed 4 years ago by timmywil

  • Status changed from closed to reopened
  • Resolution duplicate deleted

It shouldn't be different from html. That is interesting. Have you tried using  http://api.jquery.com/load ? Load performs the insert by first attaching the given html to a disconnected div. This might solve the problem, but it's hard to know exactly. If you update your test case, I'll take another look.

comment:8 Changed 4 years ago by timmywil

  • Owner set to jaraco
  • Status changed from reopened to pending

comment:9 follow-up: ↓ 12 Changed 4 years ago by dmethvin

So widget_source is text of an XML document? You're not supposed to try and parse XML with $(), especially on IE, but you could try $.parseXML(). That still leaves the problem of how to get XML nodes into an HTML document. Because no matter what you do, any IE before IE9 does not support XHTML. Or were you talking about IE9 here?

Do you have a test case?

comment:10 in reply to: ↑ 7 Changed 4 years ago by jaraco

  • Status changed from pending to new

Replying to timmywil:

Have you tried using  http://api.jquery.com/load ?

If I try to use .load, I run into #8941 (which occurs even on Firefox 4). Here's  an example that attempts to load the strict XHTML widget.xhtml (and included below for posterity).

<!DOCTYPE html 
     PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
     "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.5.2/jquery.js" type="text/javascript"></script>
  <script type="text/javascript">
// Load and init the widget
$(document).ready(function (){$('#main_cont').load('widget.xhtml div');});
  </script>
</head>
<body>

  <div id="main_cont">
  </div>

</body>
</html>

comment:11 Changed 4 years ago by timmywil

  • Keywords xhtml added
  • Status changed from new to closed
  • Resolution set to invalid

Ok then. I looked into it a little more based on Dave's comment and if you are serving these files with Content-Type xhtml, they will not be supported in IE<9. Servers (especially static ones) will base the Content-Type off the file extension. My suggestion is to change your file extensions to .html and make sure they are being served with correct text/html header and they should load fine even with the xhtml DOCTYPE. Or, if you prefer, you can set your server to respond with an xhtml content-type only for user agents which support xhtml and html for the rest. At that point, your file extension will make no difference. Closing as I don't think this is an issue with jQuery.

comment:12 in reply to: ↑ 9 Changed 4 years ago by jaraco

Replying to dmethvin:

So widget_source is text of an XML document?

I could have named the variable better. widget_source is the result of the .get() call, which does some content-type detection. Since the source is of the type application/xhtml+xml, widget_source ends up being an IXMLDomDocument2 on IE9. On Firefox, it ends up being a vanilla Document, which is why .append() accepts it (or a clone at least).

That still leaves the problem of how to get XML nodes into an HTML document. Because no matter what you do, any IE before IE9 does not support XHTML. Or were you talking about IE9 here?

In the context of this bug, I am talking about IE9, though ultimately I need to support IE7 and preferably IE6. I do, though, want to use XHTML, because this is part of a componentized system where the components that are being loaded should be machine-readable and as structured as possible.

If it's the case that jQuery does not or cannot support loading XHTML in a cross-browser way (at this time), that is acceptable, but I need to reach that conclusion formally so I know I'm not just misinterpreting the usage.

All indications from the forums and bugs and common sense tell me this is possible without altering the widget source.

Do you have a test case?

Yes, the  test case originally referenced does reproduce the problem in IE9.

comment:13 Changed 4 years ago by dmethvin

Sorry, I'm lazily coming up to speed. I missed the link in the original ticket and didn't read the forum post.

This isn't a limitation in jQuery, it's one in IE. The XML nodes can't be inserted into an HTML document. XML documents are pretty inflexible in IE, for example we can't add expando properties to IE's XML nodes either.

The technique you mentioned in your forum post is probably the solution you'll need to take. There's a reason why people prefer JSON to XML nowadays...

comment:14 Changed 2 years ago by mudyc

Simple workaround by converting xml to string and then running with jquery, e.g.

function xml_to_string(xml_node) {
  if (xml_node.xml)
    return xml_node.xml;
  else if (XMLSerializer) {
    var xml_serializer = new XMLSerializer();
    return xml_serializer.serializeToString(xml_node);
  } else {
    alert("ERROR: Extremely old browser");
    return "";
  }
}

Usage:

$.get('some_xml_data.xml', function(data) {
  $('#the-element').append($(xml_to_string(data)));
});
Note: See TracTickets for help on using tickets.