XSL escape character issue

I write this because I really hit the wall and cannot go forward. In my database, I eluded HTML as follows: "<p>My name is Freddy and I was" . "<p>My name is Freddy and I was"

I want to show it as HTML or cut HTML tags in my XSL template. Both solutions will work for me and I will choose a faster solution.

I read several posts on the Internet, but cannot find a solution. I also tried disabling output / output without success. Basically the problem is that somewhere in the XSL version the engine changes this <p> to this: <p> .

Converts & to & . If that helps, here is my XSL code. I tried several combinations with and without an output tag at the top.

Any help would be appreciated. Thanks in advance.

 <?xml version="1.0" encoding="utf-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="html" omit-xml-declaration="yes"/> <xsl:template match="DocumentElement"> <div> <xsl:attribute name="id">mySlides</xsl:attribute> <xsl:apply-templates> <xsl:with-param name="templatenumber" select="0"/> </xsl:apply-templates> </div> <div> <xsl:attribute name="id">myController</xsl:attribute> <xsl:apply-templates> <xsl:with-param name="templatenumber" select="1"/> </xsl:apply-templates> </div> </xsl:template> <xsl:template match="DocumentElement/QueryResults"> <xsl:param name="templatenumber">tobereplace</xsl:param> <xsl:if test="$templatenumber=0"> <div> <xsl:attribute name="id">myController</xsl:attribute> <div> <xsl:attribute name="class">article</xsl:attribute> <h2> <a> <xsl:attribute name="class">title</xsl:attribute> <xsl:attribute name="title"><xsl:value-of select="Title"/></xsl:attribute> <xsl:attribute name="href">/stories/stories-details/articletype/articleview/articleid/<xsl:value-of select="ArticleId"/>/<xsl:value-of select="SEOTitle"/>.aspx</xsl:attribute> <xsl:value-of select="Title"/> </a> </h2> <div> <xsl:attribute name="style">text-indent: 25px;</xsl:attribute> <xsl:attribute name="class">articlesummary</xsl:attribute> <xsl:call-template name="removeHtmlTags"> <xsl:with-param name="html" select="Summary" /> </xsl:call-template> </div> </div> </div> </xsl:if> <xsl:if test="$templatenumber=1"> <div> <xsl:attribute name="id">myController</xsl:attribute> <span> <xsl:attribute name="class">jFlowControl</xsl:attribute> aa </span> </div> </xsl:if> </xsl:template> <xsl:template name="removeHtmlTags"> <xsl:param name="html"/> <xsl:choose> <xsl:when test="contains($html, '&lt;')"> <xsl:value-of select="substring-before($html, '&lt;')"/> <!-- Recurse through HTML --> <xsl:call-template name="removeHtmlTags"> <xsl:with-param name="html" select="substring-after($html, '&gt;')"/> </xsl:call-template> </xsl:when> <xsl:otherwise> <xsl:value-of select="$html"/> </xsl:otherwise> </xsl:choose> </xsl:template> </xsl:stylesheet> 
+8
html escaping xslt
Mar 14 '09 at 16:24
source share
4 answers

Based on the assumption that you have this HTML line,

 <p>My name is Freddy &amp; I was 

then if you avoid it and save it in the database, it will become the following:

 &lt;p&gt;My name is Freddy &amp;amp; I was 

Therefore, if you extract it as XML (without pre-attaching it in advance), the result will be the following:

 &amp;lt;p&amp;gt;My name is Freddy &amp;amp;amp; I was 

and <xsl:value-of select="." disable-output-escaping="yes" /> <xsl:value-of select="." disable-output-escaping="yes" /> produce:

 &lt;p&gt;My name is Freddy &amp;amp; I was 

You get the same as in your database, but, of course, you see HTML tags in the output. So, you need a mechanism that performs the following string replacements:

  • "&amp;lt;" with "&lt;" (effectively changing &lt; to < in an unshielded release)
  • "&amp;gt;" with "&gt;" (effectively changing &gt; to > in unescaped ouput)
  • "&amp;quot;" with "&quot;" (effectively changing &quot; to " in unshielded output)
  • "&amp;amp;" with "&amp;" (effectively changing &amp; to & in unshielded output)

From your XSL, I inferred the following XML test input:

 <DocumentElement> <QueryResults> <Title>Article 1</Title> <ArticleId>1</ArticleId> <SEOTitle>Article_1</SEOTitle> <Summary>&amp;lt;p&amp;gt;Article 1 summary &amp;amp;amp; description.&amp;lt;/p&amp;gt;</Summary> </QueryResults> <QueryResults> <Title>Article 2</Title> <ArticleId>2</ArticleId> <SEOTitle>Article_2</SEOTitle> <Summary>&amp;lt;p&amp;gt;Article 2 summary &amp;amp;amp; description.&amp;lt;/p&amp;gt;</Summary> </QueryResults> </DocumentElement> 

I modified the stylesheet that you provided and implemented such a replacement mechanism. If you apply the following XSLT 1.0 template to it:

 <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:my="my:namespace" exclude-result-prefixes="my" > <xsl:output method="html" omit-xml-declaration="yes"/> <my:unescape> <my:char literal="&lt;" escaped="&amp;lt;" /> <my:char literal="&gt;" escaped="&amp;gt;" /> <my:char literal="&quot;" escaped="&amp;quot;" /> <my:char literal="&amp;" escaped="&amp;amp;" /> </my:unescape> <xsl:template match="DocumentElement"> <div id="mySlides"> <xsl:apply-templates mode="slides" /> </div> <div id="myController"> <xsl:apply-templates mode="controller" /> </div> </xsl:template> <xsl:template match="DocumentElement/QueryResults" mode="slides"> <div class="article"> <h2> <a class="title" title="{Title}" href="{concat('/stories/stories-details/articletype/articleview/articleid/', ArticleId, '/', SEOTitle, '.aspx')}"> <xsl:value-of select="Title"/> </a> </h2> <div class="articlesummary" style="text-indent: 25px;"> <xsl:apply-templates select="document('')/*/my:unescape/my:char[1]"> <xsl:with-param name="html" select="Summary" /> </xsl:apply-templates> </div> </div> </xsl:template> <xsl:template match="DocumentElement/QueryResults" mode="controller"> <span class="jFlowControl"> <xsl:text>aa </xsl:text> <xsl:value-of select="Title" /> </span> </xsl:template> <xsl:template match="my:char"> <xsl:param name="html" /> <xsl:variable name="intermediate"> <xsl:choose> <xsl:when test="following-sibling::my:char"> <xsl:apply-templates select="following-sibling::my:char[1]"> <xsl:with-param name="html" select="$html" /> </xsl:apply-templates> </xsl:when> <xsl:otherwise> <xsl:value-of select="$html" disable-output-escaping="yes" /> </xsl:otherwise> </xsl:choose> </xsl:variable> <xsl:call-template name="unescape"> <xsl:with-param name="html" select="$intermediate" /> </xsl:call-template> </xsl:template> <xsl:template name="unescape"> <xsl:param name="html" /> <xsl:choose> <xsl:when test="contains($html, @escaped)"> <xsl:value-of select="substring-before($html, @escaped)" disable-output-escaping="yes"/> <xsl:value-of select="@literal" disable-output-escaping="yes" /> <xsl:call-template name="unescape"> <xsl:with-param name="html" select="substring-after($html, @escaped)"/> </xsl:call-template> </xsl:when> <xsl:otherwise> <xsl:value-of select="$html" disable-output-escaping="yes"/> </xsl:otherwise> </xsl:choose> </xsl:template> </xsl:stylesheet> 

This HTML output is then output:

 <div id="mySlides"> <div class="article"> <h2> <a class="title" title="Article 1" href="/stories/stories-details/articletype/articleview/articleid/1/Article_1.aspx">Article 1</a> </h2> <div class="articlesummary" style="text-indent: 25px;"> <p>Article 1 summary &amp; description.</p> </div> </div> <div class="article"> <h2> <a class="title" title="Article 2" href="/stories/stories-details/articletype/articleview/articleid/2/Article_2.aspx">Article 2</a> </h2> <div class="articlesummary" style="text-indent: 25px;"> <p>Article 2 summary &amp; description.</p> </div> </div> </div> <div id="myController"> <span class="jFlowControl">aa Article 1</span> <span class="jFlowControl">aa Article 2</span> </div> 

Note

  • using a temporary namespace and embedded elements ( <my:unescape> ) to create a list of characters to replace
  • using recursion to emulate iteratively replacing all affected characters in the input
  • using an implicit context in a unescape template to transfer information whose symbol you want to replace at the moment

Also note:

  • using template modes to get another output for a single input (this replaces your templatenumber parameter)
  • In most cases, <xsl:attribute> elements are not needed. They can be safely replaced with the built-in notation ( attributename="{attributevalue}" )
  • using concat() to create a url

Generally speaking, it is a bad idea to store shielded HTML in a database (generally speaking: It is a bad idea to store HTML in a database). You ask yourself all the problems, this is one of them. If you cannot change this setting, I hope the solution helps you.

I cannot guarantee that he does the right thing in all situations, and he can open security holes (think about XSS), but that was not part of the question. In any case, think about yourself.

I need a break.; -)

+18
Mar 15 '09 at 14:22
source share

You should not store escaped HTML in your database. If your database contains the actual value of the "<" character, then the disable-output-escaping command will do what you wanted.

If you cannot change the data, you will need to delete the data before performing the conversion.

+6
Mar 14 '09 at 16:38
source share

Add this line to the stylesheet

 <xsl:output method="html" indent="yes" version="4.0"/> 
+2
Jan 17 '12 at 15:56
source share

Bad idea to store HTML in a database

What? How should you store it? In an XML document to use XSLT? As a web developer, we always used SQL databases to store custom HTML data. There is nothing wrong with this method if it is properly cleaned for your purposes.

+1
Feb 01 '10 at 0:37
source share



All Articles