SitePoint Sponsor

User Tag List

Results 1 to 6 of 6
  1. #1
    One website at a time mmj's Avatar
    Join Date
    Feb 2001
    Location
    Melbourne Australia
    Posts
    6,282
    Mentioned
    1 Post(s)
    Tagged
    0 Thread(s)

    XHTML, Safari/Konqueror and <script>

    In creating an XHTML parser I have discovered a problem with the way Safari treats character data inside a <script> element.

    I'll illustrate what I mean through example. Consider the following code, which appears somewhere within an XHTML document.

    Code:
    <script>
    document.write('<');
    </script>
    A second glance at this code will make the problem obvious - any complaint parser is going to break when it reaches the '<'. This is because the < is interpreted as the beginning of a tag.

    Current browsers will treat this '<' as a literal and the code will work, which is forgivable since this doesn't break the XHTML standard.

    Rightly so, this will break an XHTML or XML validator. Presuming you intended the '<' to be literal, the way to do this is:

    Code:
    <script>
    document.write('&lt;');
    </script>
    This code will validate as expected in an XHTML and XML validator, because it's valid code. When it gets to the Javascript, it will also behave just as expected: it will write the letter '<' to in the document. The reason it's correct is that a compliant parser will always interpret this &lt; entity as a '<' character before returning the data.

    However, I was using Safari today and I discovered something disturbing: The Javascript writes '&lt;' literally to the document. In other words, the parser in that browser conditionally 'forgets' about XHTML compliance when inside a <script> element (other &lt; entities in the same document, but not in <script> element, were interpreted correctly). This behaviour actually breaks the XHTML standard. In the short time I was fiddling with this, I didn't find any circumstances in which I could get Safari to behave in a compliant way, although Safari may have been in a 'quirks' mode which I am not aware of.

    The problem is that there is no way of working around this in Safari except to break XHTML compliance, or use a hack such as the following:

    Code:
    <script>
    <!--
    document.write('<');
    // -->
    </script>
    This is now both XHTML compliant, and will work with Safari. It's XHTML compliant in that an complaint XML parser will treat all characters (apart from the '--' at the end) in an XML comment as a comment. The problem is that it's not technically valid Javascript - it's a hack, and it relies on the fact that most browsers will ignore the fact that the comment exists, and treat the comment as Javascript.

    For now, I am going to stick with the second example, because it is the only one that is fully compliant and uses no hacks.

    Can somebody confirm what I'm saying by testing the second sample in Safari? What do you get? You should see '<' written to the document. I might be wrong.
    [mmj] My magic jigsaw
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    The Bit Depth Blog Twitter Contact me
    Neon Javascript Framework Jokes Android stuff

  2. #2
    Robert Wellock silver trophybronze trophy xhtmlcoder's Avatar
    Join Date
    Apr 2002
    Location
    A Maze of Twisty Little Passages
    Posts
    6,316
    Mentioned
    60 Post(s)
    Tagged
    0 Thread(s)
    Albeit if you were serving XHTML as an application of XML you should see nothing... or get an error. Have you tried using an external file and calling it by a function, I don't have Safari or I would test it.

  3. #3
    SitePoint Evangelist ClevaTreva's Avatar
    Join Date
    Jan 2004
    Location
    Chipping Campden, UK
    Posts
    403
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Hi

    What happens if you use the ascii code instead?

    &#60




    Trevor

  4. #4
    SitePoint Addict
    Join Date
    Sep 2003
    Location
    Europe
    Posts
    222
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    You should use this:
    <script> <![CDATA[
    ]]> </script>
    But the better way IMHO is to use external scripts.

  5. #5
    One website at a time mmj's Avatar
    Join Date
    Feb 2001
    Location
    Melbourne Australia
    Posts
    6,282
    Mentioned
    1 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by yngwin
    You should use this:
    <script> <![CDATA[
    ]]> </script>
    Yes, I know that should be possible. However, does this work in Safari? Given that safari'sw parser doesn't seem to recognise any XML entities inside a script tag, can it be trusted to recognise CDATA? This solution is also not compatible with non-XML parsers - that is, browsers that were made before XML or XHTML were invented. That is, it breaks backward compatibility.
    [mmj] My magic jigsaw
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    The Bit Depth Blog Twitter Contact me
    Neon Javascript Framework Jokes Android stuff

  6. #6
    SitePoint Guru
    Join Date
    Mar 2004
    Location
    Earth
    Posts
    406
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Well I don't get the same results as you. In HTML mode Safari and moz both print "<" in response to either document.write("<") or document.write("&lt;").

    In XHTML mode moz doesn't print anything - it generates a DOM parsing exception "node cannot be created in this context" - but that's because it doesn't support document.write in XHTML mode. Safari still outputs it the same, because Safari doesn't support XHTML mode.

    I don't think there is a solution from inline scripting that both works and is valid - the only alternative afaik is something like this:
    Code:
    document.getElementById("someNode").appendChild(document.createTextNode("<"))
    But obviously you can't do that from inline scripting either, and you can't create an entity with createTextNode, and you can't use the createEntityReference method either because no browser implements it.


Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •