Search code examples
javascriptxmlperlxml-twig

xml twig: output unescaped text


I'm using Perl's XML::Twig module to transform XML into (X)HTML. I need to output a Javascript element that looks like this:

<script type="text/javascript">window.onload = function(){for(i = 1; i < 5; i++)collapse("tbl" + i);}</script>

Since the script contains "<", which is not XML-approved, when I call $node->set_text($code);, it is escaped as "<", which breaks it. How do I output text without escaping it? If that's impossible or bad, how do I get around it?


Solution

  • If you want the XHTML to be well-formed you still have to escape the '<'. Which of course Javascript would not like.

    So the solution is to put the script in a CDATA section, which you get in XML::Twig by giving the element the tag '#CDATA'

    Here is how you would create a CDATA section:

    perl -MXML::Twig -E'say XML::Twig::Elt->new( script)->set_cdata( "a<b")->sprint'
    # <script><![CDATA[a<b]]></script>
    

    If you want to wrap all the scripts in CDATA, here is how to do it:

    #!/usr/bin/perl
    
    use strict;
    use warnings;
    
    use XML::Twig;
    
    XML::Twig->new( twig_roots => { script => sub { if( my $s= $_->text) { $_->set_cdata( $s); }
                                                    $_->print;
                                                  },
                                  },
                     twig_print_outside_roots => 1,
                  )
              ->parsefile( $ARGV[0]);
    

    This will only wrap local scripts, and will not double-wrap the ones which are already wrapped.