4

我正在寻找各种转换,但我正在尝试获取构成已找到字符的十六进制字符串的实际字符串。所以,如果 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"/>

...给出实际文本 '�' 而不是字符 ''

我试过代码点到字符串,但这没有帮助。一定有一些我没有找到的功能,因为我不确定如何在没有获得所有这些转换建议的情况下提出问题。

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

提前致谢

4

1 回答 1

4

什么是有用的解决方案似乎取决于您为什么想要字符的十六进制表示。

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

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

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

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

<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;. (如上所述 - 如果你想要的只是获取数字字符引用在输出而不是文字中,这不是要采取的方法。)

于 2013-06-20T02:03:45.053 回答