【问题标题】:How to force escaping of every double quote " into the XML character entity "如何强制将每个双引号“转义为 XML 字符实体”
【发布时间】:2015-09-24 15:25:58
【问题描述】:

如何将字符串中的所有" 转换为"

例子:

来源数据:<String>"ACCOUNT_DETAILS" : "75"</String>

目标数据: <String>"ACCOUNT_DETAILS" : "75"</String>

PS:我使用的是 XSLT 1.0。我尝试在“XSLT string replace”进行讨论,但没有成功。

【问题讨论】:

    标签: xml xslt escaping xslt-1.0 soa


    【解决方案1】:

    你为什么想做这样的事情?从 XML 的角度来看,"" 完全相同。并且任何 XSLT 处理器(或相关的 XML 库)在单引号和双引号作为文字出现在属性中时都会正确转义,这通常是它们需要分别转义为 '" 的唯一地方。

    但是,如果有一些您必须这样做的奇怪要求(有很多工具仅部分支持 XML 或其某些变体),您可以执行以下操作:

    <xsl:text disable-output-escaping="yes">&amp;quot;</xsl:text>
    

    这将输出&amp;amp;quot;。请注意,处理器不需要支持disable-output-escaping,即使支持,它也不必服从,从 XSLT 2.0 开始,您应该改用xsl:character-map,这是一个更好、更灵活的替代方案.

    使用 XSLT 1.0 的字符串替换模板

    您可能跟进的问题是如何将这种技术应用于整个字符串。由于 XSLT 1.0 没有良好的字符串搜索和替换功能,您必须使用递归调用模板。对于练习(我对 XSLT 1.0 有点生疏,通常使用 XSLT 2.0 或更高版本,其中这是一个单行),我想我会再试一次,因为以前的缘故。

    这适用于您的输入:

    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
        version="1.0">
    
        <xsl:variable name="input">"ACCOUNT_DETAILS" : "75"</xsl:variable>
    
        <xsl:template match="/">
            <xsl:variable name="result">
                <xsl:call-template name="replace">
                    <xsl:with-param name="string" select="$input"/>
                    <xsl:with-param name="search" select="'&quot;'" />
                    <xsl:with-param name="replace-with" select="'&amp;quot;'" />
                </xsl:call-template>
            </xsl:variable>
            <xsl:value-of select="$result" disable-output-escaping="yes" />
        </xsl:template>
    
        <xsl:template name="replace">
            <xsl:param name="string" />
            <xsl:param name="search" />
            <xsl:param name="replace-with" />        
            <xsl:choose>
                <xsl:when test="contains($string, $search)">
                    <xsl:value-of select="substring-before($string, $search)" />
                    <xsl:value-of select="$replace-with" />
                    <xsl:call-template name="replace">
                        <xsl:with-param name="string" select="substring-after($string, $search)" />
                        <xsl:with-param name="search" select="$search" />
                        <xsl:with-param name="replace-with" select="$replace-with" />
                    </xsl:call-template>
                </xsl:when>
                <xsl:otherwise>
                    <xsl:value-of select="$string" />
                </xsl:otherwise>
            </xsl:choose>
        </xsl:template>
    
    </xsl:stylesheet>
    

    和输出:

    &quot;ACCOUNT_DETAILS&quot; : &quot;75&quot;
    

    编辑:使用 JSON 转义 \"

    在您编写的 cmets 中,您需要 JSON。使用 JSON 转义可能更容易,因为它们在 XML 中没有特殊含义。

    把我上面的代码调用如下,去掉disable-output-escaping:

    <xsl:call-template name="replace">
        <xsl:with-param name="string" select="$input"/>
        <xsl:with-param name="search" select="'&quot;'" />
        <xsl:with-param name="replace-with" select="'\&quot;'" />
    </xsl:call-template>
    

    或者,如果您想要 XML 样式的转义,而不是直接将 &amp;amp;quot; 写入输出流(这只是编写 " 的另一种方式,任何 XML 解析器都会这样解释),您可以加倍- 使用上面相同的代码转义引号,但不使用disable-output-escaping。然后文字 XML 将包含 &amp;amp;quot,您的浏览器或 XML 解析器会将其视为 &amp;amp;quot;(在转义之后)。

    【讨论】:

    • 感谢 Abel 的快速回复。 1.我试过你的解决方案。在测试中,输出为:"ACCOUNT_DETAILS" : "75"。看起来,XSLT 处理器将其转换回正常形式,如您之前所述。我正在使用 JDeveloper 12.1.3.0 进行操作。 2. 我正在将来自 pl/sql 的 JSON 输出公开为休息服务。在这种情况下,JSON 输出中的所有" 在作为休息服务公开时都会转换为\"。所以,我认为将" 转换为&amp;amp;quot; 可能会有所帮助。我为此问题提出了另一个question
    • @NameetNayan,那么最好 (1) 使用具有原生 JSON 支持的 XSLT 3.0 处理器(您使用的是 Java,应该不难找到 Saxon)和 (2 ) 如果你不能/不能,逃到\"。我怀疑 XSLT 是否“将它们转换回来”,我假设您正在浏览器中查看它,它会将 &amp;amp;quot; 解释为 "。如果您希望浏览器显示为&amp;amp;quot;,只需从代码中删除disable-output-escaping,它将为您提供&amp;amp;quot;,它“看起来像”&amp;amp;quot;。虽然我建议简单地更改上面的代码以替换为 JSON 转义 \"
    • @NameetNayan,我已经更新了答案,以展示如何将相同的代码与 JSON 转义一起使用,或者如何使用 XML 转义进行双重转义。
    • Abel,我忘了感谢您将标题编辑为更有意义的标题。 :) [1] 我在 xsltransform.net 尝试了您的第一个解决方案,它在那里运行良好。不确定,问题可能出在我正在使用的 JDeveloper IDE 上。 [2] 关于&lt;xsl:with-param name="replace-with" select="'\&amp;quot;'" /&gt; ,它在执行时将所有“替换为\”。我想,我可能没有正确地澄清这个问题,因为这不是我想要的。这样,rest 服务的最终输出为\\\"ACCOUNT_DETAILS\\\" : \\\"75\\\"
    • @nameet,如果你看到的结果有三个反斜杠,那么在转换之后你正在做一些额外的事情。与消失的引用相同,您确定直接转换到磁盘而不是发送到浏览器的流字符串吗?因为可能涉及很多额外的处理和转义。
    【解决方案2】:

    我认为在 XSLT 2.0 中应该可以使用字符映射:http://xsltransform.net/pPzifoT/1。在 XSLT 1.0 中,您可以使用命名模板,将双引号替换为 &lt;xsl:text disable-output-escaping="yes"&gt;&lt;![CDATA[&amp;quot;]]&gt;&lt;/xsl:text&gt;

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-10-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-11-24
      • 1970-01-01
      相关资源
      最近更新 更多