...

View Full Version : <table> elements imported incorrectly by importNode?



joris
05-02-2006, 03:26 PM
Hi all,

I'm using Firefox 1.0.8, and try to replace innerHTML with a combination of DOMParser(), importNode, and replaceChild(). However, the XHTML code fragment I'm trying to insert contains a <table> element and seems to be imported incorrectly.

I've got the following XHTML:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<title>FooBar</title>
<script type="text/javascript" src="foobar.js"></script>
</head>

<body onload="foobar();">
</body>
</html>

and here's foobar.js (note: this snippet uses appendChild instead of replaceChild).

<!--
function foobar()
{
var fragment, parser, parsed_fragment, node;

fragment = "<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\"><table id=\"foobar\"><tr><td>foo<\/td><\/tr><tr><td>bar<\/td><\/tr><\/table><\/div>";

parser = new DOMParser();
parsed_fragment = parser.parseFromString(fragment, "application/xhtml+xml");
node = document.importNode(parsed_fragment.documentElement, true);
document.body.appendChild(node);
alert(document.getElementById("foobar").rows.length);
}
//-->

Now, as the XHTML fragment defines a table with two rows, I would expect the alert() on the last line to show '2', but I got '0'. The DOM Inspector shows that the table has no tbody. However, the fragment is valid XHTML as far as I know, so shouldn't the tbody be generated automatically (like in any XHTML page)?
Any help would be appreciated.
Thanks,

Joris van Zwieten

Kor
05-02-2006, 03:39 PM
as long as you have imported it using innerHTML non-standard method instead of DOM methods, the table will not not be able to insert in your page's DOM tree.

have you tried cloneNode(true) method

joris
05-02-2006, 04:13 PM
Kor: many thanks for your reply. However, I'm afraid I don't really understand what you're saying. As you can see in the code, I'm not using innerHTML anywhere.

Kor
05-02-2006, 04:28 PM
sorry, I was quickly thinking in term of HTML DOM, not XHTML DOM. I'll switch my mind to it to see if I find an answer.

liorean
05-02-2006, 08:07 PM
Well, I've messed around a little with your code.

"CF post 85783.xhtml" (of type "application/xhtml+xml"):
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-gb">
<head>
<title>Using DOMParser, importNode, and document traversal in an XHTML as XHTML file</title>
<script type="application/ecmascript" src="CF post 85783.js"/>
</head>
<body>
<h1>Using DOMParser, importNode, and document traversal in an XHTML as XHTML file</h1>
<p>Tries to attach a div written in source form in a string, parsed by <code>DOMParser</code>, and imported using <code>importNode</code> into the document. Then tries to get the table node contained in that div using <code>getElementById</code>.</p>
<h2>Example</h2>
</body>
</html>


And "CF post 85783.js" (of type "application/ecmascript"):
function foobar(e){
alert('foobar entered');
var
fragment='<div xmlns="http://www.w3.org/1999/xhtml"><table id="foobar"><tr><td>foo</td></tr><tr><td>bar</td></tr></table></div>',
parser=new DOMParser(),
parsed_fragment=parser.parseFromString(fragment,"application/xhtml+xml"),
node=document.importNode(parsed_fragment.documentElement,true);
document.getElementsByTagNameNS('http://www.w3.org/1999/xhtml','body')
.item(0).appendChild(node);
alert((node=document.getElementById("foobar"))+'\n'+node.rows+'\n'+(length in node.rows)+'\n'+node.rows.length);
}

window.addEventListener('load',foobar,true);


And things I see:
1. It's bad coding style to use event handlers embedded in markup, especially on the body element. Try to keep the markup in one file, and script in another file where possible.

2. In XHTML sent as XHTML, don't use document.body. That's an HTMLism that should be kept in the HTML world.

3. If you have your script in a separate file, you should NOT include the HTML/XML comments or CDATA blocks. Also, there's no need to escape "</" if the JavaScript is in a separate file, since there's no SGML, HTML or XML parser involved.

4. If you use ' as your quoting character in JavaScript, and " in HTML/XML, you can avoid the need to escape the quoting character of HTML/XML inside a JavaScript string.

5. Firefox doesn't correctly support the rows HTMLCollection if you don't have a tbody in your table.

6. Opera doesn't have that problem.

7. To play well with firefox, use tbody.

8. A tbody should ALWAYS be present in all tables in XHTML anyway (W3C went and made a bad design decision when they allowed them to be excluded, since they were required - but with optional start and end tags - in HTML), so just go and add it.

joris
05-03-2006, 08:38 AM
liorean: thanks very much for your comments. I don't code javascript that often, so I really appreciate the comments on coding style. As for the other points, adding a tbody indeed did the job! :)

I also found a comment on: http://www.mozilla.org/docs/web-developer/faq.html#xhtmldiff that could be related. It seems that the XML parser used by firefox (expat) does "not infer tbody, head, body, and html if the tags are not explicitly present." So that would explain the absence of the tbody. However, I think it's still weird that firefox renders a table correctly without a tbody, but does not support the rows property in that case.
Thanks again for your help,

joris



EZ Archive Ads Plugin for vBulletin Copyright 2006 Computer Help Forum