Исходя из предположения, что у вас есть эта строка HTML,
<p>My name is Freddy & I was
тогда, если вы избежите его и сохраните в базе данных, оно станет this :
<p>My name is Freddy &amp; I was
Следовательно, если вы извлекаете его как XML (без предварительного удаления), результат будет this :
&lt;p&gt;My name is Freddy &amp;amp; I was
и <xsl:value-of select="." disable-output-escaping="yes" />
будут производить:
<p>My name is Freddy &amp; I was
Вы получаете то же самое, что и в своей базе данных, но, конечно, вы видите HTML-теги в выводе. Итак, вам нужен механизм, который выполняет следующие замены строк:
"&lt;"
с "<"
(эффективное изменение <
на <
в выходном сигнале без экранирования)
"&gt;"
с ">"
(эффективное изменение >
на >
в выходном сигнале без экранирования)
"&quot;"
с """
(эффективное изменение "
на "
в выходном сигнале без экранирования)
"&amp;"
с "&"
(эффективное изменение &
на &
в выходном сигнале без экранирования)
Из вашего XSL я вывел следующий тестовый ввод XML:
<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>
Я изменил предоставленную вами таблицу стилей и реализовал такой механизм замены. Если вы примените к нему следующий шаблон XSLT 1.0:
<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>
Затем выводится HTML:
<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>
Примечание
- использование временного пространства имен и встроенных элементов (
<my:unescape>
) для создания списка символов для замены
- использование рекурсии для эмуляции итеративной замены всех задействованных символов во входных данных
- использование неявного контекста в шаблоне
unescape
для передачи информации о том, какой символ должен быть заменен в данный момент
Кроме того, примечание:
- использование шаблонных режимов для получения разных выходных данных для одного и того же ввода (это заменяет ваш параметр
templatenumber
)
- в большинстве случаев нет необходимости в
<xsl:attribute>
элементах. Их можно смело заменять встроенными обозначениями (attributename="{attributevalue}"
)
- использование функции
concat()
для создания URL
Вообще говоря, хранить экранированный HTML в базе данных - плохая идея (в более общем смысле: хранить HTML в базе данных - плохая идея). Вы настроены на то, чтобы получать всевозможные проблемы, и это одна из них. Если вы не можете изменить эту настройку, я надеюсь, что решение поможет вам.
Я не могу гарантировать, что он работает правильно во всех ситуациях, и это может открыть дыры в безопасности (например, XSS), но решение этой проблемы не было частью вопроса. В любом случае считайте себя предупрежденным.
Мне нужен перерыв сейчас. ; -)