【问题标题】:Double-unescaping raw HTML inside XSL?在 XSL 中双重转义原始 HTML?
【发布时间】:2013-11-01 18:39:08
【问题描述】:

我正在处理一个 XML 文件,该文件将原始 HTML 存储在节点的属性 () 中。

我刚刚意识到 HTML 是双重编码的,所以,而不是:

<div>

其实写成:

<div>

这意味着如果我这样做:

<xsl:value-of select="node/@data" disable-output-escaping="yes" />

我仍然会得到一个(单个)转义值:

&lt;div&gt;

再次摆脱这种情况的最简单方法是什么?

【问题讨论】:

    标签: html xml xslt


    【解决方案1】:

    这绝对不漂亮,但基本上你正在查看数量有限的字符串替换操作

    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
      <xsl:output method="html" encoding="utf-8" />
    
      <xsl:variable name="ampDbl" select="'&amp;amp;'" />
      <xsl:variable name="amp" select="'&amp;'" />
      <xsl:variable name="ltDbl" select="'&amp;lt;'" />
      <xsl:variable name="lt" select="'&lt;'" />
      <xsl:variable name="gtDbl" select="'&amp;gt;'" />
      <xsl:variable name="gt" select="'&gt;'" />
    
      <xsl:template match="/">
        <xsl:apply-templates select="//@data" mode="unescape" />
      </xsl:template>
    
      <xsl:template match="@data" mode="unescape">
        <xsl:variable name="step1">
          <xsl:call-template name="StringReplace">
            <xsl:with-param name="s" select="string()" />
            <xsl:with-param name="search" select="$ltDbl" />
            <xsl:with-param name="replace" select="$lt" />
          </xsl:call-template>
        </xsl:variable>
        <xsl:variable name="step2">
          <xsl:call-template name="StringReplace">
            <xsl:with-param name="s" select="$step1" />
            <xsl:with-param name="search" select="$gtDbl" />
            <xsl:with-param name="replace" select="$gt" />
          </xsl:call-template>
        </xsl:variable>
        <xsl:variable name="step3">
          <xsl:call-template name="StringReplace">
            <xsl:with-param name="s" select="$step2" />
            <xsl:with-param name="search" select="$ampDbl" />
            <xsl:with-param name="replace" select="$amp" />
          </xsl:call-template>
        </xsl:variable>
        <xsl:value-of select="$step3" disable-output-escaping="yes" />
      </xsl:template>
    
      <!-- generic string replace template -->
      <xsl:template name="StringReplace">
        <xsl:param name="s"       select="''" />
        <xsl:param name="search"  select="''" />
        <xsl:param name="replace" select="''" />
    
        <xsl:choose>
          <xsl:when test="contains($s, $search)">
            <xsl:value-of select="substring-before($s, $search)" />
            <xsl:value-of select="$replace" />
            <xsl:variable name="rest" select="substring-after($s, $search)" />
            <xsl:if test="$rest">
              <xsl:call-template name="StringReplace">
                <xsl:with-param name="s"       select="$rest" />
                <xsl:with-param name="search"  select="$search" />
                <xsl:with-param name="replace" select="$replace" />
              </xsl:call-template>
            </xsl:if>
          </xsl:when>
          <xsl:otherwise>
            <xsl:value-of select="$s" />
          </xsl:otherwise>
        </xsl:choose>
      </xsl:template>
    </xsl:stylesheet>
    

    当应用于

    <root>
      <node data="&amp;lt;div&amp;gt;bla &amp;amp;amp; bla&amp;lt;/div&amp;gt;" />
    </root>
    

    给出(在源代码中)

    <div>bla &amp; bla</div>
    

    当然会在屏幕上变成这样:

    bla & bla

    您可能想要为'&amp;amp;quot;' 添加一个step4'&amp;quot;'

    【讨论】:

    • FWIW,我很久以前在another answer做了相反的操作(双转义输出)
    • 哇,你说得对,它不漂亮,但它有效:) 直到有人能想出更好的方法,并将其标记为答案。谢谢!
    • @Amberite 如果您的 XSLT 处理器支持扩展功能(如 EXSLT 或专有扩展方法之一,如 .NET 提供的一种或 MSXSL 脚本扩展),那么您可能能够关闭 -将繁重的工作加载到更适合字符串处理和 HMTL 解析的外部例程中。以上是vanilla XSLT 1.0 方法。如果您拥有的不仅仅是 vanilla XSLT 1.0,请务必使用它。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-01-24
    • 2013-02-26
    相关资源
    最近更新 更多