You have an XSL template for the website you are working on and you would like to embed some JavaScript in the markup. You care so you would like to keep the XHTML output valid. Easy enough - all it takes is wrapping the actual JavaScript code with CDATA. To make it safe you would also add JS comments around CDATA and move on. But is it really that easy with XSL? Let's have a look.
XSL template for JavaScript
Here is the working solution which allows for safe embedding JavaScript on XHTML pages created with XSL templates.
Example 0
<?xml version="1.0" encoding="UTF-8"?> <xsl:transform version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="xml" encoding="utf-8" doctype-public="-//W3C//DTD XHTML 1.0 Strict//EN" doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd" indent="yes" cdata-section-elements="" omit-xml-declaration="yes" /> <xsl:template name="javascript"> <xsl:param name="code"/> <xsl:text disable-output-escaping="yes"> <script type="text/javascript"> /* <![CDATA[ */ </xsl:text> <xsl:value-of select="$code" disable-output-escaping="yes"/> <xsl:text disable-output-escaping="yes"> /* ]]> */ </script> </xsl:text> </xsl:template> <xsl:template match="/"> <html> <body> <xsl:call-template name="javascript"> <xsl:with-param name="code"> <![CDATA[ if (1 > 2) {} ]]> </xsl:with-param> </xsl:call-template> </body> </html> </xsl:template> </xsl:transform>
The above example will output:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <body> <script type="text/javascript"> /* <![CDATA[ */ if (1 > 2) {} /* ]]> */ </script> </body> </html>
Can it be simpler?
Let's start off with the most intuitive approach - add CDATA inside script tag as you would in XHTML.
Example 1
<?xml version="1.0" encoding="UTF-8"?> <xsl:transform version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="xml" encoding="utf-8" doctype-public="-//W3C//DTD XHTML 1.0 Strict//EN" doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd" indent="yes" cdata-section-elements="" omit-xml-declaration="yes" /> <xsl:template match="/"> <html> <body> <script type="text/javascript"> /* <![CDATA[ */ if (1 < 2) {} /* ]]> */ </script> </body> </html> </xsl:template> </xsl:transform>
The above example will output:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <body> <script type="text/javascript"> /* */ if (1 < 2) {} /* */ </script> </body> </html>
CDATA got stripped off and the < sign got replaced with <. Of course! CDATA as an XML specific construct is interpreted in XSL as well. And that helps - try to remove CDATA from the following example and you will see an error. Good old < is the source of trouble here - without CDATA around, it makes XML invalid.
The interpreted CDATA should stay then but another CDATA is required in the output. xls:output has an option which allows to wrap content of certain tags with CDATA. However if you set it up to wrap up content of script tags with CDATA (the rest of the code like in example 1) you will not get what you need. Let's have a look.
Example 2
cdata-section-elements="script"
The above example will output:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <body> <script type="text/javascript"> <![CDATA[ /* */ if (1 < 2) {} /* */ ]]> </script> </body> </html>
Ok, now there is CDATA in the output but it is not safely commented out. And it does not seem possible to get it that way. And how about creating CDATA explicitly as a text? Maybe with disabled output escaping that would work? Let's see.
Example 3
<?xml version="1.0" encoding="UTF-8"?> <xsl:transform version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="xml" encoding="utf-8" doctype-public="-//W3C//DTD XHTML 1.0 Strict//EN" doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd" indent="yes" cdata-section-elements="" omit-xml-declaration="yes" /> <xsl:template match="/"> <html> <body> <script type="text/javascript"> <xsl:text disable-output-escaping="yes"> /* <![CDATA[ */ </xsl:text> <![CDATA[ if (1 < 2) {} ]]> <xsl:text disable-output-escaping="yes"> /* ]]> */ </xsl:text> </script> </body> </html> </xsl:template> </xsl:transform>
The above example will output:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <body> <script type="text/javascript"> /* <![CDATA[ */ if (1 < 2) {} /* ]]> */ </script> </body> </html>
That's definitely some progress, CDATA is in place. Now the < in the JavaScript code should become < again. Why not to put the whole JavaScript code into another xsl:text tag with disable escaping? Well, that's why:
Example 4
<script type="text/javascript"> <xsl:text disable-output-escaping="yes"> /* <![CDATA[ */ </xsl:text> <xsl:text disable-output-escaping="yes"> <![CDATA[ if (1 < 2) {} ]]> </xsl:text> <xsl:text disable-output-escaping="yes"> /* ]]> */ </xsl:text> </script>
The above example will output:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <body> <script type="text/javascript"> /* <![CDATA[ */ if (1 < 2) {} /* ]]> */ </script> </body> </html>
Is it a dead end or maybe xsl:text element is not the best choice after all? It has to be something with disable-output-escaping attribute. Another such an element is xsl:value-of. Assuming that the JavaScript code exists only in the template and not in the processed XML structure, value-of needs an xsl:variable to read value from.
Example 5
<xsl:variable name="s1"> <![CDATA[ if (1 < 2) {} ]]> </xsl:variable> <script type="text/javascript"> <xsl:text disable-output-escaping="yes"> /* <![CDATA[ */ </xsl:text> <xsl:value-of select="$s1" disable-output-escaping="yes"/> <xsl:text disable-output-escaping="yes"> /* ]]> */ </xsl:text> </script>
The above example will output:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <body> <script type="text/javascript"> /* <![CDATA[ */ if (1 < 2) {} /* ]]> */ </script> </body> </html>
And that worked! It is not very flexible solution, though. Defining variable for every JavaScript in the template seems to be acceptable only if necessary. Luckily xsl:value-of can also read value of a parameter passed to an xsl:template. That's how I got to the template you can find at the top of the page.
Thank you for reading. I hope you found it useful.
Update - 21.05.2010
At the beginning the template looked like this:
<xsl:template name="javascript"> <xsl:param name="code"/> <script type="text/javascript"> <xsl:text disable-output-escaping="yes"> /* <![CDATA[ */ </xsl:text> <xsl:value-of select="$code" disable-output-escaping="yes"/> <xsl:text disable-output-escaping="yes"> /* ]]> */ </xsl:text> </script> </xsl:template>
However it turned out that on some PHP installations XSLT adds CDATA inside <script> tag even if it's not specified in the <xsl:output>. Therefore <script> tag has to be generated as a text rather than being part of interpreted XML.
Jacek
Hello,
ReplyDeleteYou can also have a look at my solution which work in all major browsers (IE, Firefox, Chrome, Opera):
http://www.gabsoftware.com/tips/extending-xhtml-with-xml-xsl-transformations-entities-cdata-sections-javascript/
What if you need to use XSLT tags within the "code" param?
ReplyDeleteFor example:
< xsl:call-template name="javascript" >
< xsl:with-param name="code" >
< ![CDATA[
var x = < xsl:value-of select="$x"/ >
var y = < xsl:value-of select="$y"/ >
if (x > y) {}
]]>
< /xsl:with-param >
< /xsl:call-template >
Thank you so much for this! I've been fiddling with this issue all morning.
ReplyDeleteNice post .Keep updating UI online course Bangalore
ReplyDeleteThis is quite educational arrange. It has famous breeding about what I rarity to vouch. Colossal proverb. This trumpet is a famous tone to nab to troths. Congratulations on a career well achieved. This arrange is synchronous s informative impolite festivity to pity. I appreciated what you ok extremely here.
ReplyDeleteangularjs Training in bangalore
angularjs Training in electronic-city
angularjs Training in online
angularjs Training in marathahalli
Thank you so much for a well written, easy to understand article on this. It can get really confusing when trying to explain it – but you did a great job. Thank you!
ReplyDeleteJava training in Chennai | Java training in Bangalore
Java interview questions and answers | Core Java interview questions and answers
I really like your blog. You make it interesting to read and entertaining at the same time. I cant wait to read more from you.
ReplyDeleteData Science Training in Indira nagar | Data Science Training in btmlayout
Python Training in Kalyan nagar | Data Science training in Indira nagar
Data Science Training in Marathahalli | Data Science Training in BTM Layout
thanks for your post azure training in hyderabad
ReplyDeletethis is the fantastic post to learn pl sql training
ReplyDeleteThe Blog is really excellent one.
ReplyDeleteAzure Training in Chennai | Certification | Azure Online Training Course | Azure Training in Bangalore | Certification | Azure Online Training Course | Azure Training in Hyderabad | Certification | Azure Online Training Course | Azure Training in Pune | Certification | Azure Online Training Course | Azure Training | microsoft azure certification | Azure Online Training Course
Kayseri
ReplyDeleteAnkara
Kilis
Sakarya
Bursa
ZJTUAN
goruntulu show
ReplyDeleteücretli
KNCN
istanbul evden eve nakliyat
ReplyDeleteurfa evden eve nakliyat
konya evden eve nakliyat
tunceli evden eve nakliyat
denizli evden eve nakliyat
QXR
https://istanbulolala.biz/
ReplyDeletePİL
ığdır evden eve nakliyat
ReplyDeletebitlis evden eve nakliyat
batman evden eve nakliyat
rize evden eve nakliyat
niğde evden eve nakliyat
82XNİ
ığdır evden eve nakliyat
ReplyDeletebitlis evden eve nakliyat
batman evden eve nakliyat
rize evden eve nakliyat
niğde evden eve nakliyat
77X4V0
06E7F
ReplyDeleteErzincan Lojistik
Bilecik Parça Eşya Taşıma
Isparta Evden Eve Nakliyat
Batman Parça Eşya Taşıma
Antep Parça Eşya Taşıma
0305E
ReplyDeleteGümüşhane Şehirler Arası Nakliyat
Bitmex Güvenilir mi
Yozgat Şehirler Arası Nakliyat
İstanbul Evden Eve Nakliyat
Denizli Evden Eve Nakliyat
Kırklareli Şehir İçi Nakliyat
Ardahan Şehir İçi Nakliyat
Antep Şehirler Arası Nakliyat
Düzce Parça Eşya Taşıma
6F112
ReplyDeleteÜnye Oto Elektrik
Kırklareli Lojistik
Coin Nedir
Erzincan Şehir İçi Nakliyat
Gümüşhane Evden Eve Nakliyat
İstanbul Şehir İçi Nakliyat
Hatay Lojistik
Tekirdağ Cam Balkon
Denizli Şehirler Arası Nakliyat
CBA50
ReplyDeleteMersin Lojistik
Ünye Kurtarıcı
Batıkent Fayans Ustası
Kilis Şehirler Arası Nakliyat
Malatya Şehir İçi Nakliyat
Bursa Lojistik
Van Şehir İçi Nakliyat
Lunc Coin Hangi Borsada
Chat Gpt Coin Hangi Borsada
39815
ReplyDeleteHatay Evden Eve Nakliyat
Urfa Evden Eve Nakliyat
Samsun Şehirler Arası Nakliyat
Ünye Oto Lastik
Kucoin Güvenilir mi
Karaman Lojistik
Poloniex Güvenilir mi
Bitget Güvenilir mi
Trabzon Parça Eşya Taşıma
46A8F
ReplyDeletereferans kodu binance
40916
ReplyDeletebinance %20
0D9DB
ReplyDeletekayseri muhabbet sohbet
manisa rastgele sohbet
uşak en iyi görüntülü sohbet uygulamaları
giresun canlı görüntülü sohbet siteleri
adana en iyi ücretsiz sohbet siteleri
muğla canlı sohbet ücretsiz
antep tamamen ücretsiz sohbet siteleri
karabük canlı sohbet uygulamaları
samsun kızlarla canlı sohbet
F6E26
ReplyDeleteAğrı Görüntülü Sohbet Odaları
Muğla Sohbet Siteleri
hakkari bedava sohbet uygulamaları
en iyi ücretsiz sohbet uygulamaları
nevşehir mobil sohbet odaları
bingöl ücretsiz sohbet uygulaması
Bilecik Canlı Görüntülü Sohbet Uygulamaları
antalya bedava sohbet odaları
chat sohbet
839A4
ReplyDeleteantalya canlı sohbet et
şırnak ücretsiz sohbet siteleri
sohbet muhabbet
telefonda kadınlarla sohbet
Afyon Mobil Sohbet Bedava
tekirdağ sesli sohbet mobil
rastgele sohbet
telefonda kızlarla sohbet
Kırşehir Görüntülü Sohbet Ücretsiz
AA0A8
ReplyDeleteInstagram Beğeni Hilesi
Binance Kimin
Bitcoin Kazanma
Referans Kimliği Nedir
Okex Borsası Güvenilir mi
Linkedin Beğeni Satın Al
Kripto Para Nasıl Üretilir
Twitter Beğeni Hilesi
Vector Coin Hangi Borsada
3952A
ReplyDeleteSoundcloud Takipçi Satın Al
Okex Borsası Güvenilir mi
Bitcoin Hesap Açma
Binance Borsası Güvenilir mi
Bulut Madenciliği Nedir
Facebook Takipçi Hilesi
Threads Takipçi Satın Al
Binance Referans Kodu
Kripto Para Nasıl Alınır
AC994
ReplyDeleteClubhouse Takipçi Hilesi
Raca Coin Hangi Borsada
Bitcoin Kazma
Threads Takipçi Satın Al
Spotify Takipçi Satın Al
Aptos Coin Hangi Borsada
Ceek Coin Hangi Borsada
Binance Nasıl Üye Olunur
Tumblr Takipçi Hilesi
A7ACD
ReplyDeleteavalaunch
pancakeswap
layerzero
pudgy penguins
satoshivm
zkswap
pancakeswap
uwulend finance
poocoin
3A6F5
ReplyDeletesushiswap
phantom wallet
uwulend finance
thorchain
debank
quickswap
pancakeswap
zkswap
dexview