Based on the assumption that you have this HTML line,
<p>My name is Freddy & I was
then if you avoid it and save it in the database, it will become the following:
<p>My name is Freddy &amp; I was
Therefore, if you extract it as XML (without pre-attaching it in advance), the result will be the following:
&lt;p&gt;My name is Freddy &amp;amp; I was
and <xsl:value-of select="." disable-output-escaping="yes" /> <xsl:value-of select="." disable-output-escaping="yes" /> produce:
<p>My name is Freddy &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:
"&lt;" with "<" (effectively changing < to < in an unshielded release)"&gt;" with ">" (effectively changing > to > in unescaped ouput)"&quot;" with """ (effectively changing " to " in unshielded output)"&amp;" with "&" (effectively changing & 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>&lt;p&gt;Article 1 summary &amp;amp; description.&lt;/p&gt;</Summary> </QueryResults> <QueryResults> <Title>Article 2</Title> <ArticleId>2</ArticleId> <SEOTitle>Article_2</SEOTitle> <Summary>&lt;p&gt;Article 2 summary &amp;amp; description.&lt;/p&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="<" escaped="&lt;" /> <my:char literal=">" escaped="&gt;" /> <my:char literal=""" escaped="&quot;" /> <my:char literal="&" escaped="&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 & 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 & 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.; -)