XSLT替换变量中的双引号。

时间:2022-04-06 16:48:54

Just to clarify, I am using XSLT 1.0. Sorry for not specifying that at first.

澄清一下,我使用的是XSLT 1.0。很抱歉一开始没有具体说明。

I have an XSLT stylesheet where I'd like to replace double quotes with something safe that's safe to go into a JSON string. I'm trying to do something like the following:

我有一个XSLT样式表,我想用一个安全的JSON字符串替换双引号。我试着做如下的事情:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="text" omit-xml-declaration="yes" />
  <xsl:strip-space elements="*" />

  <xsl:template match="/message">
    <xsl:variable name="body"><xsl:value-of select="body"/></xsl:variable>


    {
      "message" : 
      {
        "body":  "<xsl:value-of select="normalize-space($body)"/>"
      }
    }
  </xsl:template>
</xsl:stylesheet>

If I have XML passed in that looks like the following, this will always work just fine:

如果我输入了如下所示的XML,这将始终正常工作:

<message>
 <body>This is a normal string that will not give you any issues</body>
</message>

However, I'm dealing with a body that has full blown HTML in it, which isn't an issue because normalize-space() will take care of the HTML, but not double quotes. This breaks me:

但是,我正在处理一个包含完整HTML的主体,这不是问题,因为normalize-space()将处理HTML,而不是双引号。这个优惠我:

<message>
<body>And so he quoted: "I will break him". The end.</body>
</message>

I really don't care if the double quotes are HTML escaped or prefixed with a backslash. I just need to make sure the end result passes a JSON parser.

我真的不在乎双引号是HTML转义还是以反斜杠为前缀。我只需要确保最终结果通过JSON解析器。

This output passes JSON Lint and would be an appropriate solution (backslashing the quotes):

这个输出经过JSON Lint,将是一个合适的解决方案(回调引号):

{ "body" : "And so he quoted: \"I will break him\". The end." } 

2 个解决方案

#1


8  

Using a recursive template, you can perform the replace. This example replaces " with \"

使用递归模板,可以执行替换。这个例子用“\”代替了“\”

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="text" omit-xml-declaration="yes" />
    <xsl:strip-space elements="*" />

    <xsl:template match="/message">
        <xsl:variable name="escaped-body">
            <xsl:call-template name="replace-string">
                <xsl:with-param name="text" select="body"/>
                <xsl:with-param name="replace" select="'&quot;'" />
                <xsl:with-param name="with" select="'\&quot;'"/>
            </xsl:call-template>
        </xsl:variable>


        {
        "message" : 
        {
        "body":  "<xsl:value-of select="normalize-space($escaped-body)"/>"
        }
        }
    </xsl:template>

    <xsl:template name="replace-string">
        <xsl:param name="text"/>
        <xsl:param name="replace"/>
        <xsl:param name="with"/>
        <xsl:choose>
            <xsl:when test="contains($text,$replace)">
                <xsl:value-of select="substring-before($text,$replace)"/>
                <xsl:value-of select="$with"/>
                <xsl:call-template name="replace-string">
                    <xsl:with-param name="text"
                        select="substring-after($text,$replace)"/>
                    <xsl:with-param name="replace" select="$replace"/>
                    <xsl:with-param name="with" select="$with"/>
                </xsl:call-template>
            </xsl:when>
            <xsl:otherwise>
                <xsl:value-of select="$text"/>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>
</xsl:stylesheet>

And produces the output:

和生成的输出:

{
"message" : 
{
"body":  "And so he quoted: \"I will break him\". The end."
}
}

#2


2  

What version of XSLT? Keep in mind that many characters require special escaping in JSON. While this is technically possible in XSLT, it won't be pretty.

什么版本的XSLT ?记住,许多字符在JSON中需要特殊转义。虽然在XSLT中这是可行的,但它不会很漂亮。

If you really just care about the backslash, though, and you're using XSLT 1.0, any of the various string replace templates should do it for you.

但是,如果您真的只关心反斜杠,并且正在使用XSLT 1.0,那么任何不同的字符串替换模板都应该为您做。

#1


8  

Using a recursive template, you can perform the replace. This example replaces " with \"

使用递归模板,可以执行替换。这个例子用“\”代替了“\”

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="text" omit-xml-declaration="yes" />
    <xsl:strip-space elements="*" />

    <xsl:template match="/message">
        <xsl:variable name="escaped-body">
            <xsl:call-template name="replace-string">
                <xsl:with-param name="text" select="body"/>
                <xsl:with-param name="replace" select="'&quot;'" />
                <xsl:with-param name="with" select="'\&quot;'"/>
            </xsl:call-template>
        </xsl:variable>


        {
        "message" : 
        {
        "body":  "<xsl:value-of select="normalize-space($escaped-body)"/>"
        }
        }
    </xsl:template>

    <xsl:template name="replace-string">
        <xsl:param name="text"/>
        <xsl:param name="replace"/>
        <xsl:param name="with"/>
        <xsl:choose>
            <xsl:when test="contains($text,$replace)">
                <xsl:value-of select="substring-before($text,$replace)"/>
                <xsl:value-of select="$with"/>
                <xsl:call-template name="replace-string">
                    <xsl:with-param name="text"
                        select="substring-after($text,$replace)"/>
                    <xsl:with-param name="replace" select="$replace"/>
                    <xsl:with-param name="with" select="$with"/>
                </xsl:call-template>
            </xsl:when>
            <xsl:otherwise>
                <xsl:value-of select="$text"/>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>
</xsl:stylesheet>

And produces the output:

和生成的输出:

{
"message" : 
{
"body":  "And so he quoted: \"I will break him\". The end."
}
}

#2


2  

What version of XSLT? Keep in mind that many characters require special escaping in JSON. While this is technically possible in XSLT, it won't be pretty.

什么版本的XSLT ?记住,许多字符在JSON中需要特殊转义。虽然在XSLT中这是可行的,但它不会很漂亮。

If you really just care about the backslash, though, and you're using XSLT 1.0, any of the various string replace templates should do it for you.

但是,如果您真的只关心反斜杠,并且正在使用XSLT 1.0,那么任何不同的字符串替换模板都应该为您做。