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

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

问题描述

我正在写这个,因为我真的打了墙,不能前进。在我的数据库中,我已经转义了这样的HTML:& lt; p& gt;我的名字是Freddy,我是



我想将其显示为HTML或剥离我的XSL模板中的HTML标签。这两个解决方案都适用于我,我将选择更快的解决方案。



我已经在线阅读了几篇帖子,但找不到解决方案。我也尝试了禁用输出逃生,没有成功。基本上看来,问题是XSL执行中的某个地方引擎正在将这个& lt; p& gt; 改为: amp; amp ; lt; p& amp; gt;



正在转换& 进入& amp; amp; amp; amp; amp; amp;< / code>。如果有帮助,这里是我的XSL代码。我已经尝试过几个组合,有和没有输出标签在顶部。



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

 <?xml version =1.0encoding =utf-8?> 
< xsl:stylesheet version =1.0xmlns:xsl =http://www.w3.org/1999/XSL/Transform>

< xsl:output method =htmlomit-xml-declaration =yes/>

< xsl:template match =DocumentElement>
< div>
< xsl:attribute name =id> mySlides< / xsl:attribute>
< xsl:apply-templates>
< xsl:with-param name =templatenumberselect =0/>
< / xsl:apply-templates>
< / div>

< div>
< xsl:attribute name =id> myController< / xsl:attribute>
< xsl:apply-templates>
< xsl:with-param name =templatenumberselect =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 =htmlselect =摘要/>
< / 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;'')/>
<! - 通过HTML重复 - >
< xsl:call-template name =removeHtmlTags>
< xsl:with-param name =htmlselect =substring-after($ html,'& gt;')/>
< / xsl:call-template>
< / xsl:when>
< xsl:否则>
< xsl:value-of select =$ html/>
< / xsl:否则>
< / xsl:choose>
< / xsl:template>
< / xsl:stylesheet>


解决方案

假设您有 HTML字符串

 < p>我的名字是Freddy& amp; amp;我是

那么如果你逃避它并将其存储在数据库中,它将成为 / em>:

 & lt; p& gt我的名字是Freddy& amp; amp; amp;我是

因此,如果您将其作为XML检索(不预先将其解码),结果将是这个

 & amp; lt; p& amp; ;安培;放大器;放大器;我是

< xsl:value-of select =。 disable-output-escaping =yes/> 将产生:

 & p& gt;我的名字是Freddy& amp; amp; amp; amp;我是

你在数据库中拥有完全一样的东西,但当然你会看到输出中的HTML标签。所以你需要的是一个机制来执行以下字符串替换:




  • & amp; & lt(有效地将& lt 更改为< 在未转义的输出中)

  • & amp; amp; & gt(有效地将& gt; 更改为 code> in unescaped oupup)

  • & amp; quot; with & ; (有效地将& quot; 更改为在未转义的输出中)

  • & amp; amp; amp;& amp;(有效地将& amp; amp; amp; 更改为& in unescaped ouput)



从您的XSL我推断出以下测试输入XML:

 < DocumentElement> 
< QueryResults>
< Title>第1条< / Title>
< ArticleId> 1< / ArticleId>
< SEO标题> Article_1< / SEOTitle>
<摘要& amp; amp; amp; amp& amp; amp; amp; amp; amp; amp; amp; amp; amp; amp; amp; amp; amp; amp; amp; amp; amp; amp; amp; amp;描述&安培;安培; LT; / P&放大器;放大器; GT;< /总结>
< / QueryResults>
< QueryResults>
< Title>第2条< / Title>
< ArticleId> 2< / ArticleId>
< SEOTitle> Article_2< / SEOTitle>
<摘要& amp; amp; amp; amp& amp;>>第2条总结& amp; amp; amp;描述&安培;安培; LT; / P&放大器;放大器; GT;< /总结>
< / 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 =htmlomit-xml-declaration =yes/>

< my:unescape>
< my:char literal =& lt逃脱= &放大器;放大器; LT; />
< my:char literal =& gt逃脱= &放大器;放大器; gt; 中/>
< my:char literal =& quot逃脱= &放大器;放大器; QUOT; />
< my:char literal =& 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 / QueryResultsmode =slides>
< div class =article>
< h2>
< a class =titletitle ={Title}href ={concat('/ stories / stories-details / articletype / articleview / articleid /',ArticleId,'/',SEOTitle,的.aspx')}>
< xsl:value-of select =Title/>
< / a>
< / h2>
< div class =articlesummarystyle =text-indent:25px;>
< xsl:apply-templates select =document('')/ * / my:unescape / my:char [1]>
< xsl:with-param name =htmlselect =摘要/>
< / xsl:apply-templates>
< / div>
< / div>
< / xsl:template>

< xsl:template match =DocumentElement / QueryResultsmode =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 =htmlselect =$ html/>
< / xsl:apply-templates>
< / xsl:when>
< xsl:否则>
< xsl:value-of select =$ htmldisable-output-escaping =yes/>
< / xsl:否则>
< / xsl:choose>
< / xsl:variable>
< xsl:call-template name =unes​​cape>
< xsl:with-param name =htmlselect =$ intermediate/>
< / xsl:call-template>
< / xsl:template>

< xsl:template name =unes​​cape>
< xsl:param name =html/>
< xsl:choose>
< xsl:当test =contains($ html,@escaped)>
< xsl:value-of select =substring-before($ html,@escaped)disable-output-escaping =yes/>
< xsl:value-of select =@ literaldisable-output-escaping =yes/>
< xsl:call-template name =unes​​cape>
< xsl:with-param name =htmlselect =substring-after($ html,@escaped)/>
< / xsl:call-template>
< / xsl:when>
< xsl:否则>
< xsl:value-of select =$ htmldisable-output-escaping =yes/>
< / xsl:否则>
< / xsl:choose>
< / xsl:template>

< / xsl:stylesheet>

然后,此输出HTML生成:

 < div id =mySlides> 
< div class =article>
< h2>
< a class =titletitle =第1条href =/ stories / stories-details / articletype / articleview / articleid / 1 / Article_1.aspx>第1条< / a>
< / h2>
< div class =articlesummarystyle =text-indent:25px;>
< p>第1条总结& amp; 。描述< / p为H.
< / div>
< / div>
< div class =article>
< h2>
< a class =titletitle =第2条href =/ stories / stories-details / articletype / articleview / articleid / 2 / Article_2.aspx>第2条< / a>
< / h2>
< div class =articlesummarystyle =text-indent:25px;>
< p>第2条总结& amp; 。描述< / p为H.
< / div>
< / div>
< / div>
< div id =myController>
< span class =jFlowControl> aa第1条< / span>
< span class =jFlowControl> aa第2条< / span>
< / div>

注意




  • 使用临时命名空间和嵌入元素(< my:unescape> )创建一个要替换的字符列表

  • 使用递归来模拟输入中所有受影响的字符的迭代替换

  • 使用 unescape 中的隐式上下文



此外,请注意:




  • 使用模板模式为相同的输入获取不同的输出(这取代了您的 templatenumber 参数)

  • 大部分时间不需要< xsl:attribute> 元素。他们可以安全地用内联符号替换( attributename ={attributevalue}

  • 使用 concat()函数创建URL



一般来说,存储转义数据库中的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:

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

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

  • the use of a temporary namespace and embedded elements (<my:unescape>) to create a list of characters to replace
  • the use of recursion to emulate an iterative replacement of all affected characters in the input
  • the use of the implicit context within the unescape template to transport the information which character is to be replaced at the moment

Furthermore note:

  • the use of template modes to get different output for the same input (this replaces your templatenumber parameter)
  • most of the time there is no need for <xsl:attribute> elements. They can safely be replaced by inline notation (attributename="{attributevalue}")
  • the use of the concat() function to create the URL

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天全站免登陆