XSL 字符转义问题 [英] XSL character escape problem

查看:29
本文介绍了XSL 字符转义问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我写这篇文章是因为我真的撞到了墙,无法继续.在我的数据库中,我像这样转义了 HTML:"<p>My name is Freddy and I was".

我想将其显示为 HTML 或去除 XSL 模板中的 HTML 标签.两种解决方案都适合我,我会选择更快的解决方案.

我在网上阅读了几篇文章,但找不到解决方案.我也尝试过禁用输出转义但没有成功.基本上,问题似乎是在 XSL 执行的某个地方,引擎正在将此 <p> 更改为: <p>.

它正在将 & 转换为 &.如果有帮助,这是我的 XSL 代码.我尝试了几种组合,顶部有和没有输出标签.

任何帮助将不胜感激.提前致谢.

<div><xsl:attribute name="id">myController</xsl:attribute><xsl:apply-templates><xsl:with-param name="templatenumber" select="1"/></xsl:apply-templates>

</xsl:模板><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">文章</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><div><xsl:attribute name="style">text-indent: 25px;</xsl:attribute><xsl:attribute name="class">文章摘要</xsl:attribute><xsl:call-template name="removeHtmlTags"><xsl:with-param name="html" select="Summary"/></xsl:call-template>

</xsl:if><xsl:if test="$templatenumber=1"><div><xsl:attribute name="id">myController</xsl:attribute><跨度><xsl:attribute name="class">jFlowControl</xsl:attribute>aa</span>

</xsl:if></xsl:模板><xsl:template name="removeHtmlTags"><xsl:param name="html"/><xsl:when test="contains($html, '<')"><xsl:value-of select="substring-before($html, '<')"/><!-- 通过 HTML 递归 --><xsl:call-template name="removeHtmlTags"><xsl:with-param name="html" select="substring-after($html, '&gt;')"/></xsl:call-template></xsl:when><xsl:否则><xsl:value-of select="$html"/></xsl:否则></xsl:选择></xsl:模板></xsl:stylesheet>

解决方案

基于假设你有这个 HTML 字符串,

我的名字是 Freddy &amp;我曾是

然后,如果您将其转义并将其存储在数据库中,它将成为这个:

&lt;p&gt;我的名字是弗雷迪 &amp;amp;我曾是

因此,如果您将其作为 XML 检索(没有事先对其进行转义),结果将是这个:

&amp;lt;p&amp;gt;我的名字是弗雷迪 &amp;amp;amp;我曾是

会产生:

&lt;p&gt;我的名字是弗雷迪 &amp;amp;我曾是

您将获得与数据库中完全相同的内容,但您当然会在输出中看到 HTML 标记.因此,您需要的是一种执行以下字符串替换的机制:

根据您的 XSL,我推断出以下测试输入 XML:

<查询结果><标题>第 1 条</标题><文章ID>1</文章ID><SEOTitle>文章_1</SEOTitle><概要>&amp;lt;p&gt;第1条概要&amp;amp;amp;描述.&amp;lt;/p&amp;gt;</Summary></查询结果><查询结果><标题>第 2 条</标题><ArticleId>2</ArticleId><SEOTitle>文章_2</SEOTitle><概要>&amp;lt;p&gt;第2条概要&amp;amp;amp;描述.&amp;lt;/p&amp;gt;</Summary></查询结果></DocumentElement>

我已经更改了您提供的样式表并实现了这样的替换机制.如果您将以下 XSLT 1.0 模板应用于它:

<div id="myController"><xsl:apply-templates mode="controller"/>

</xsl:模板><xsl:template match="DocumentElement/QueryResults" mode="slides"><div class="文章"><h2><a class="title" title="{Title}" href="{concat('/stories/stories-details/articletype/articleview/articleid/', ArticleId, '/', SEOTitle, '.aspx')}"><xsl:value-of select="Title"/></a><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>

</xsl:模板><xsl:template match="DocumentElement/QueryResults" mode="controller"><span class="jFlowControl"><xsl:text>aa </xsl:text><xsl:value-of select="Title"/></span></xsl:模板><xsl:template match="my:char"><xsl:param name="html"/><xsl:variable name="intermediate"><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:否则><xsl:value-of select="$html" disable-output-escaping="yes"/></xsl:否则></xsl:选择></xsl:变量><xsl:call-template name="unescape"><xsl:with-param name="html" select="$intermediate"/></xsl:call-template></xsl:模板><xsl:template name="unescape"><xsl:param name="html"/><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:否则><xsl:value-of select="$html" disable-output-escaping="yes"/></xsl:否则></xsl:选择></xsl:模板></xsl:stylesheet>

然后产生这个输出HTML:

<div class="文章"><h2><a class="title" title="Article 1" href="/stories/stories-details/articletype/articleview/articleid/1/Article_1.aspx">第1条</a><div class="articlesummary" style="text-indent: 25px;"><p>第1条概要&amp;</p>

<div class="文章"><h2><a class="title" title="Article 2" href="/stories/stories-details/articletype/articleview/articleid/2/Article_2.aspx">第2条</a><div class="articlesummary" style="text-indent: 25px;"><p>第2条概要&amp;</p>

<div id="myController"><span class="jFlowControl">aa 第 1 条</span><span class="jFlowControl">aa 第 2 条</span>

注意

另外注意:

一般来说,将转义的 HTML 存储在数据库中是一个坏主意(更一般地说:将 HTML 存储在数据库中是一个坏主意.).你让自己遇到各种各样的问题,这就是其中之一.如果您无法更改此设置,希望该解决方案对您有所帮助.

我不能保证它在所有情况下都能做正确的事情,它可能会打开安全漏洞(想想 XSS),但处理这个不是问题的一部分.无论如何,请考虑警告.

我现在需要休息一下.;-)

I am writing this because I have really hit the wall and cannot go ahead. In my database I have escaped HTML like this: "&lt;p&gt;My name is Freddy and I was".

I want to show it as HTML OR strip the HTML tags in my XSL template. Both solutions will work for me and I will choose the quicker solution.

I have read several posts online but cannot find a solution. I have also tried disable-output-escape with no success. Basically it seems the problem is that somewhere in the XSL execution the engine is changing this &lt;p&gt; into this: &amp;lt;p&amp;gt;.

It is converting the & into &amp;. If it helps, here is my XSL code. I have tried several combinations with and without the output tag on the top.

Any help will 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>

解决方案

Based in the assumption that you have this HTML string,

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

then if you escape it and store it in a database it would become this:

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

Consequently, if you retrieve it as XML (without unescaping it beforehand), the result would be this:

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

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

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

You are getting exactly the same thing you have in your database, but of course you see the HTML tags in the output. So what you need is a mechanism that does the following string replacements:

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

<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 have changed the stylesheet you supplied 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>

Then this output HTML is produced:

<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

Furthermore note:

Generally speaking, it is a bad idea to store escaped HTML in a database (more generally speaking: It is a bad idea to store HTML in a database.). You set yourself up to get all kinds of problems, this being one of them. If you can't change this setup, I hope that the solution helps you.

I cannot guarantee that it does the right thing in all situations, and it may open up security holes (think XSS), but dealing with this was not part of the question. In any case, consider yourself warned.

I need a break now. ;-)

这篇关于XSL 字符转义问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆