The entity name must immediately follow the '&' in the entity reference
Do
<script>//<![CDATA[
/* script */
//]]></script>
All answers posted so far are giving the right solutions, however no one answer was able to properly explain the underlying cause of the concrete problem.
Facelets is a XML based view technology which uses XHTML+XML to generate HTML output. XML has five special characters which has special treatment by the XML parser:
<
the start of a tag.>
the end of a tag."
the start and end of an attribute value.'
the alternative start and end of an attribute value.&
the start of an entity (which ends with;
).
In case of &
which is not followed by #
(e.g.  
,  
, etc), the XML parser is implicitly looking for one of the five predefined entity names lt
, gt
, amp
, quot
and apos
, or any manually defined entity name. However, in your particular case, you was using &
as a JavaScript operator, not as an XML entity. This totally explains the XML parsing error you got:
The entity name must immediately follow the '&' in the entity reference
In essence, you're writing JavaScript code in the wrong place, a XML document instead of a JS file, so you should be escaping all XML special characters accordingly. The &
must be escaped as &
.
So, in your particular case, the
if (Modernizr.canvas && Modernizr.localstorage &&
must become
if (Modernizr.canvas && Modernizr.localstorage &&
to make it XML-valid.
However, this makes the JavaScript code harder to read and maintain. In case when you want to continue using &
instead of &
in JavaScript code in a XML document, then you should be placing the JavaScript code in a character data (CDATA) block. Thus, in JSF terms, that would be:
<h:outputScript>
<![CDATA[
// ...
]]>
</h:outputScript>
The XML parser will interpret the block's contents as "plain vanilla" character data and not as XML and hence interpret the XML special characters "as-is".
But, much better is to just put the JS code in its own JS file which you include by <script src>
, or in JSF terms, the <h:outputScript>
.
<h:outputScript name="onload.js" target="body" />
(note the target="body"
; this way JSF will automatically render the <script>
at the very end of <body>
, regardless of where <h:outputScript>
itself is located, hereby achieving the same effect as with window.onload
and $(document).ready()
; so you don't need to use those anymore in that script)
This way you don't need to worry about XML-special characters in your JS code. As an additional bonus, this gives you the opportunity to let the browser cache the JS file so that total response size is smaller.
See also:
- Error Parsing /page.xhtml: Error Traced[line: 42] The entity "nbsp" was referenced, but not declared
- Is it possible to use JSF+Facelets with HTML 4/5?
- How to reference CSS / JS / image resource in Facelets template?
You need to add a CDATA tag inside of the script tag, unless you want to manually go through and escape all XHTML characters (e.g. &
would need to become &
). For example:
<script>
//<![CDATA[
var el = document.getElementById("pacman");
if (Modernizr.canvas && Modernizr.localstorage &&
Modernizr.audio && (Modernizr.audio.ogg || Modernizr.audio.mp3)) {
window.setTimeout(function () { PACMAN.init(el, "./"); }, 0);
} else {
el.innerHTML = "Sorry, needs a decent browser<br /><small>" +
"(firefox 3.6+, Chrome 4+, Opera 10+ and Safari 4+)</small>";
}
//]]>
</script>
The parser is expecting some HTML content, so it sees &
as the beginning of an entity, like è
.
Use this workaround:
<script type="text/javascript">
// <![CDATA[
Javascript code here
// ]]>
</script>
so you specify that the code is not HTML text but just data to be used as is.