Error parsing XHTML: The content of elements must consist of well-formed character data or markup
Solution 1
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
Solution 2
I ran across this post today as I was running into the same issue and had the same problem of the javascript not running with the CDATA tags listed above. I corrected the CDATA tags to look like:
<script type="text/javascript">
//<![CDATA[
your javascript code here
//]]>
</script>
Then everything worked perfectly!
Solution 3
Sometimes you will need this :
/*<![CDATA[*/
/*]]>*/
and not only this :
<![CDATA[
]]>
Solution 4
I had a git conflict left in my workspace.xml i.e.
<<<<———————HEAD
which caused the unknown tag error. It is a bit annoying that it doesn’t name the file.
Related videos on Youtube
Comments
-
luciaengel over 3 years
As an extension of this question, I'm trying to insert Javascript to a
<h:commandButton />
'sonclick
property asaction
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 evenfor (var i = 0; i < 10; i++)
the page wouldn't load. Why does it not like the for loop? -
luciaengel over 13 yearsThe javascript doesn't run when I use the
<![CDATA[
block or using an external js file. I shortened the code formyScript()
towindow.location='fileServlet?param=1';
, and this only runs if I put it inline withonclick
or in<script type="text/javascript"></script>
-
BalusC over 13 yearsHow did you invoke it? By
onclick="myScript()"
I suppose? -
BalusC over 13 yearsWhile wrapping in
<![CDATA[
did you ensure that you followed the instructions in the link as in my answer? There has got to be a]]>
at end. When using an external script, did you ensure that the.js
file didn't contain the<script>
, but just afunction myScript() {}
? -
luciaengel over 13 yearsyes, I used a
<![CDATA[
and]]>
block and had aglobal.js
with onlyfunction myScript() {}
-
BalusC over 13 yearsI spotted some minor errors in your JS function (among others, you omitted a
'
, but that should have resulted in a JS error, did you see it in JS console?) and the logic could be more simplified. I updated the answer with an example. -
Naganalf over 13 yearsDang it, I was typing in the same answer. Including your javascript in a separate file will definitely solve this issue, and is generally a best practice.
-
BalusC over 13 years@Naganalf: You started typing 44 minutes ago? :)
-
Naganalf over 13 yearsStarted yes, then something came up here to distract me. :P
-
luciaengel over 13 yearsThanks for the updated code. But again, running it in
global.js
like the example, even if I shorten it towindow.location='fileServlet?param=1';
it doesn't seem to run. -
BalusC over 13 years@Naganalf: Haha ok. Sorry about that :P Next time better.
-
BalusC over 13 yearsIt doesn't get invoked at all? Do you see any JS errors in the JS console? Is the
global.js
reachable anyway? (i.e. its URL is correct and so on). Web developer tools like Firebug and Web Developer Toolbar for Firefox may give lot of new insights. -
luciaengel over 13 yearsOk, after restarting server and refreshing page, clearing browser cache a couple times I got the
global.js
running. But only this partif(checked) window.location='fileServlet?param=1';
As soon as I put in the linevar box = document.getElementbyId('myForm:box');
it doesn't download the file, even when the param is currently hard-coded. I will look into using Firebug. -
BalusC over 13 yearsOnly by just putting this line? Interesting, this would suggest that calling
document
threw an exception. Anyway, is the element ID correct as per the generated HTML? -
luciaengel over 13 yearsyup, my listbox id is
box
and my form id ismyForm
It was able to get the checkbox element. -
BalusC over 13 yearsPress
Ctrl+Shift+J
to get the standard JS error console in Firefox. It might contain useful debug information. -
luciaengel over 13 yearsah I was using
getElementbyId
instead ofgetElementById
Now it triggers the download. -
luciaengel over 13 yearsThanks for tip on using external js and error console and fixing the logic too.
-
BalusC over 13 yearsAhh, my own typo. Sorry about that. Just typed straight from head :) But is it now working?
-
luciaengel over 13 yearsIt's only passing one param so far instead of the whole chain. I'm using
getParameterValues
. I'll get back to you. -
luciaengel over 13 yearsHmm, I shouldn't be doing
length - 1
, that's the options available in list box not the total of selected. I'll get back to you. -
BalusC over 13 yearsThis should actually not harm. Put an
alert(paramstring)
or with Firebug,console.log(paramstring)
beforewindow.location
to see if it's correct. -
luciaengel over 13 yearsbut the paramstring before was putting
&
at the end because it wasn't atlength - 1
even when I was already at the end of all the selections. I updated the code now, please see updated question. thanks. -
BalusC over 13 yearsI updated the answer, but I see that you used
&
in JS. This is unnecessary. The&
is only necessary when writing in a XML file. The XML parser will then turn it into a&
. -
luciaengel over 13 yearsIgnore the code that I updated, yours is outputting the correct
paramstring
and I'm getting the correct String array withgetParameterValues
. Thanks. -
BalusC over 12 yearsThis means that you're serving HTML as
application/xhtml+xml
(see also the CDATA link in my answer developer.mozilla.org/en/Writing_JavaScript_for_XHTML). Serving HTML as such is considered harmful (especially in MSIE browser). -
Sagar about 9 yearsI am using left shift operator in my code ( << ) for this it is giving me that Error parsing XHTML: The content of elements must consist of well-formed character data or markup
-
funky-nd over 6 yearsWow, how in a earth, you have found out this.