在XSLT中,如何将字符的十六进制代码作为文字文本?

时间:2013-06-20 00:45:49

标签: xslt character-encoding

我发现了各种各样的转换,但我正在尝试获取构成找到的字符的十六进制字符串的实际字符串。所以,如果是XSLT

<xsl:analyze-string select="Message" regex="([&#x1f1;-&#x1f699;])">
        <xsl:non-matching-substring>
            <xsl:value-of select="."/>
        </xsl:non-matching-substring>
        <xsl:matching-substring>
            <xsl:variable name="emjtxt"/>...

遇到XML

<Message>Very funny! </Message>

稍后在XSLT中,我想要

的结果
<xsl:value-of select="$emjtxt"/>

...给出实际的文字'&amp;#x16F60B'而不是字符''

我尝试过codepoint-to-string,但这并没有帮助。必须有一些我没有找到的功能,因为我不确定如何在没有获得所有这些转换建议的情况下提出问题。

哦,我正在使用XSLT 2和Saxon HE 9.4.0.4

提前致谢

1 个答案:

答案 0 :(得分:3)

这里有用的解决方案似乎很可能取决于你想要角色的十六进制表示的原因。

如果您只希望输出具有数字字符引用而不是U + 0020到U + 007F范围之外的字符的文字,最简单的方法是指定xsl:输出编码值命名一个不包含相关字符的字符集。输出这些字符时,它们将作为数字字符引用输出(您可能无法控制它们是十进制还是十六进制)。

如果是单个特定字符或少数字符,您感兴趣,最简单的解决方案是字符映射。从您的示例代码中,我不认为是这种情况。

如果你想对十六进制值执行一些特殊处理,,你需要一个以字符作为输入的函数,并返回表示输入字符的UCS代码点的十六进制数字。据我所知,没有内置功能可以做到这一点; nor(除非我反复忽略它)是否有一个带有整数和基数的内置函数,并返回表示该基数中该整数的字符串。所以挑战是写一个。

最简单的解决方案将问题分解为两部分:首先,编写一个接受整数的函数,并返回该整数的十六进制表示。这是一个这样的函数的简单实现(未测试):

<xsl:function name="my:i2x" as="xs:string">
  <xsl:param name="i" as="xs:integer"/>
  <xsl:choose>
    <xsl:when test="$i lt 0">
      <xsl:value-of select="concat('-', my:i2x(-1 * $i))"/>
    </xsl:when>
    <xsl:when test="$i eq 0">
      <xsl:value-of select="'0'"/>
    </xsl:when>
    <xsl:otherwise>
      <xsl:variable name="quot" select="$i idiv 16"/>
      <xsl:variable name="rmdr" select="$i mod 16"/>
      <xsl:value-of select="concat(
          my:i2x($quot),
          substring('0123456789ABCDEF', $rmdr + 1, 1)
        )"
      />
    </xsl:otherwise>
  </xsl:choose>
</xsl:function>

现在很容易编写一个包装函数来接受一个字符并在该字符的代码点上调用local:i2x():

<xsl:function name="my:c2x" as="xs:string ">
  <xsl:param name="s" as="xs:string"/>
  <xsl:choose>
    <xsl:when test="string-length($s) != 1">
      <xsl:message terminate="yes">
        The argument to local:c2x should be a single character, 
        not a longer or shorter string.
      </xsl:message>
    </xsl:when>
    <xsl:otherwise>
      <xsl:value-of select="my:i2x(string-to-codepoints($s))"/>
    </xsl:otherwise>
  </xsl:choose>
</xsl:function>

如果需要,可以让c2x()返回一个数字字符引用(但在尝试序列化时要小心,以免得到&amp;#x01F60B;而不是&#x01F60B;。(如上所述) - 如果你想要的只是在输出中获取数字字符引用而不是文字,这不是采取的方法。)