Error parsing XHTML: The content of elements must consist of well-formed character data or markup

150,579

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 &lt;.

So, essentially, the

for (var i = 0; i < length; i++) {

must become

for (var i = 0; i &lt; 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:

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.

Share:
150,579

Related videos on Youtube

luciaengel
Author by

luciaengel

New here.

Updated on January 26, 2021

Comments

  • luciaengel
    luciaengel over 3 years

    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&param=value2&param=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 + "&amp;";
                }
            } 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?

  • luciaengel
    luciaengel over 13 years
    The javascript doesn't run when I use the <![CDATA[ block or using an external js file. I shortened the code for myScript() to window.location='fileServlet?param=1';, and this only runs if I put it inline with onclick or in <script type="text/javascript"></script>
  • BalusC
    BalusC over 13 years
    How did you invoke it? By onclick="myScript()" I suppose?
  • BalusC
    BalusC over 13 years
    While 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 a function myScript() {} ?
  • luciaengel
    luciaengel over 13 years
    yes, I used a <![CDATA[ and ]]> block and had a global.js with only function myScript() {}
  • BalusC
    BalusC over 13 years
    I 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
    Naganalf over 13 years
    Dang 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
    BalusC over 13 years
    @Naganalf: You started typing 44 minutes ago? :)
  • Naganalf
    Naganalf over 13 years
    Started yes, then something came up here to distract me. :P
  • luciaengel
    luciaengel over 13 years
    Thanks for the updated code. But again, running it in global.js like the example, even if I shorten it to window.location='fileServlet?param=1'; it doesn't seem to run.
  • BalusC
    BalusC over 13 years
    @Naganalf: Haha ok. Sorry about that :P Next time better.
  • BalusC
    BalusC over 13 years
    It 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
    luciaengel over 13 years
    Ok, after restarting server and refreshing page, clearing browser cache a couple times I got the global.js running. But only this part if(checked) window.location='fileServlet?param=1'; As soon as I put in the line var 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
    BalusC over 13 years
    Only 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
    luciaengel over 13 years
    yup, my listbox id is box and my form id is myForm It was able to get the checkbox element.
  • BalusC
    BalusC over 13 years
    Press Ctrl+Shift+J to get the standard JS error console in Firefox. It might contain useful debug information.
  • luciaengel
    luciaengel over 13 years
    ah I was using getElementbyId instead of getElementById Now it triggers the download.
  • luciaengel
    luciaengel over 13 years
    Thanks for tip on using external js and error console and fixing the logic too.
  • BalusC
    BalusC over 13 years
    Ahh, my own typo. Sorry about that. Just typed straight from head :) But is it now working?
  • luciaengel
    luciaengel over 13 years
    It's only passing one param so far instead of the whole chain. I'm using getParameterValues. I'll get back to you.
  • luciaengel
    luciaengel over 13 years
    Hmm, 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
    BalusC over 13 years
    This should actually not harm. Put an alert(paramstring) or with Firebug, console.log(paramstring) before window.location to see if it's correct.
  • luciaengel
    luciaengel over 13 years
    but the paramstring before was putting &amp; at the end because it wasn't at length - 1 even when I was already at the end of all the selections. I updated the code now, please see updated question. thanks.
  • BalusC
    BalusC over 13 years
    I updated the answer, but I see that you used &amp; in JS. This is unnecessary. The &amp; is only necessary when writing in a XML file. The XML parser will then turn it into a &.
  • luciaengel
    luciaengel over 13 years
    Ignore the code that I updated, yours is outputting the correct paramstring and I'm getting the correct String array with getParameterValues. Thanks.
  • BalusC
    BalusC over 12 years
    This 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
    Sagar about 9 years
    I 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
    funky-nd over 6 years
    Wow, how in a earth, you have found out this.