Error parsing XHTML: The content of elements must consist of well-formed character data or markup
facelets, javascript, jsf, jsf-2, xhtml
Solution
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 `<`, the XML parser is implicitly looking for the tag name and the end tag `>`. However, in your particular case, you were using `<` as a JavaScript operator, not as an XML entity. This totally explains the XML parsing error you got:
The content of elements must consist of well-formed character data or markup.
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, essentially, the
for (var i = 0; i < length; i++) {
must become
for (var i = 0; i < length; i++) {
to make it XML-valid.
However, this makes the JavaScript code harder to read and maintain. As stated in Mozilla Developer Network's excellent document Writing JavaScript for XHTML, 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="functions.js" target="head" />
This way you don't need to worry about XML-special characters in your JS code. Additional advantage is that this gives the browser the opportunity to cache the JS file so that average response size is smaller.
See also:
- The entity name must immediately follow the '&' in the entity reference
- Is it possible to use JSF+Facelets with HTML 4/5?
- How to reference CSS / JS / image resource in Facelets template?
- Writing JavaScript for XHTML
Problem
As an extension of this question, I'm trying to insert Javascript to a `<h:commandButton />`'s `onclick` property as `action` is already rendering an ajax table. What I want to do: Get the selected items in a list box and turn them into parameters to be used in a JSF `FileServlet`. i.e. `para2=value1¶m=value2¶m=value3` Here's what I have: ``` <script type ="text/javascript"> function myScript() { var box = document.getElementbyId('myForm:box'); var length = box.options.length; var paramstring = ""; for (var i = 0; i < length; i++) { if (i != (length - 1) { if (box.options[i].selected) { paramstring = paramstring + "param=" + box.options[i].value + "&"; } } else { paramstring = paramstring + "param=" + box.options[i].value; } } if (document.getElementById('myForm:checkbox').checked) { window.location='fileServlet? + paramstring; } } </script> ``` What I get when page is loaded: `javax.servlet.ServletException: Error Parsing /page.xhtml: Error Traced[line:15] The content of elements must consist of well-formed character data or markup.` What doesn't trigger exception: ``` <script type ="text/javascript"> function myScript() { var box = document.getElementbyId('myForm:box'); var length = box.options.length; var paramstring = ""; if (document.getElementById('myForm:checkbox').checked) { window.location='fileServlet? + paramstring; } } </script> ``` As soon as I add in `for (var i = 0; i < length; i++)` or even `for (var i = 0; i < 10; i++)` the page wouldn't load. Why does it not like the for loop?