3

我正在使用一个 XML 文件,该文件将原始 HTML 存储在节点的属性 (<node data="HTML...">) 中。

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

&lt;div&gt;

它实际上是这样写的:

&amp;lt;div&amp;gt;

这意味着如果我执行以下操作:

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

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

&lt;div&gt;

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

4

1 回答 1

2

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

<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>

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

布拉和布拉

您可能想要添加一个step4for '&amp;quot;'to '&quot;'

于 2013-11-01T21:45:00.100 回答