Mike Starov
Mike Starov

Reputation: 7326

Can't run JavaScript in CDATA

I am trying to run following HTML in every browser: Opera, FF, IE, Chrome

<!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" xml:lang="en" lang="en">
 <head>
  <meta http-equiv="Content-Type" content="application/xhtml+xml; charset=utf-8">
 </head>
 <body>
  <script>
  <![CDATA[
     alert('Hey!');
  ]]>
  </script>
 </body>
</html>

None of them display the alert. Chrome logs an error in console: Uncaught SyntaxError: Unexpected token <. It seems to be complaining about the fist < in CDATA declaration. Firefox also logs "syntax error"

The w3schools point out that this is the way to use CDATA http://www.w3schools.com/xml/xml_cdata.asp. Other answers on this site suggest it. What am I doing wrong? I tried playing with namespaces and doctypes, but that did not change anything.

Edit: I added XHTML name space and doctype, that I originally removed and the problem still persists.

Upvotes: 5

Views: 13015

Answers (5)

danorton
danorton

Reputation: 12025

The difference is between HTML and XHTML. W3Schools is correct that it’s a valid CDATA construct within XHTML, but as your question indicates that your code is HTML and there is no such thing as CDATA inside a <script> in HTML, your example fails as soon as the interpreter sees the "<". You can tell the browser that it’s looking at XHTML, but it's probably safer to handle HTML, too. To do that, you need to hide the CDATA inside JavaScript comments. (You might also consider identifying which language is inside your <script> block.)

<html>
 <head>
 </head>
 <body>
  <script>
  //<![CDATA[
     alert('Hey!');
  //]]>
  </script>
 </body>
</html>

This is, in fact, the method recommended by the World Wide Web Consortium (W3C) in XHTML Media Types, A.4. Embedded Style Sheets and Scripts.

Upvotes: 7

Alohci
Alohci

Reputation: 83071

You may see it as XML (XHTML) but that's not how the browser sees it.

You're serving it a text/html which means that the browser sees it as HTML.

It needs to be served with an XML mime type such as application/xhtml+xml

i.e. like this

http://www.alohci.net/application/xhtml+xml/starov.htm.ashx

and not like this

http://www.alohci.net/text/html/starov.htm.ashx

Check the view source to see that it's the same file. Check the "Net" tab in firebug (or the equivalent for your browser) to see the content type in the response headers.

Upvotes: 2

Daniel Moses
Daniel Moses

Reputation: 5858

1) Comment your CDATA

  //<![CDATA[
     alert('Hey!');
  //]]>

2) add a script type

<script type="text/javascript">

Upvotes: 0

rjz
rjz

Reputation: 16510

Also, you need to comment out the CDATA so it won't throw a parsing error when it's run:

<script>
//<![CDATA[
     alert('Hey!');
//]]>
</script>

Upvotes: 1

Pekka
Pekka

Reputation: 449763

The related question When is a CDATA section necessary within a script tag? explains that a CDATA section is recommended when embedding scripts in XHTML documents. However, just setting a XHTML doctype to the test document isn't enough. The CDATA is still being treated as a syntax error.

According to this blog post, that is because the content type needs to match the doctype definition. Proper XHTML needs to have the following Content-type header set:

Content-type: application/xhtml+xml

if that is not specified and text/html sent instead, browsers will revert to HTML. And indeed, if I add that header to my test case, browsers start properly parsing the JavaScript inside the CDATA even when the CDATA it's not commented out.

This works for me (setting the header using PHP):

<?php header("Content-type: application/xhtml+xml"); 
      echo '<?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" xml:lang="en" lang="en">
  <head>
    <script><![CDATA[alert('Hey!');]]></script>
  </head>
  <body>
  </body>
 </html>​

Upvotes: 6

Related Questions