Bug Tracker

Opened 10 years ago

Closed 10 years ago

Last modified 8 years ago

#8972 closed bug (invalid)

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

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

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 (14)

comment:1 Changed 10 years ago by Jason R. Coombs

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

comment:2 Changed 10 years ago by timmywil

Component: unfiledajax
Priority: undecidedlow
Resolution: duplicate
Status: newclosed

comment:3 Changed 10 years ago by timmywil

Duplicate of #8941.

comment:4 Changed 10 years ago by Jason R. Coombs

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 10 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 10 years ago by Jason R. Coombs

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 Changed 10 years ago by timmywil

Resolution: duplicate
Status: closedreopened

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 10 years ago by timmywil

Owner: set to Jason R. Coombs
Status: reopenedpending

comment:9 Changed 10 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 10 years ago by Jason R. Coombs

Status: pendingnew

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 10 years ago by timmywil

Keywords: xhtml added
Resolution: invalid
Status: newclosed

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 10 years ago by Jason R. Coombs

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 10 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 8 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.