You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在DataPower适用的XSLT中实现Long转十六进制及解析逻辑?

解决办法

针对你要把VB的Long转ANSI字符逻辑搬到DataPower XSLT里的需求,分步骤来实现:

第一步:把输入的十六进制字符串补成8位(前导补0)

不管输入的十六进制字符串长短,先补前导0凑够8位,比如输入111就变成00000111。用XSLT字符串处理就能搞定:

<xsl:variable name="hex-input" select="'111'" />
<!-- 补0到8位 -->
<xsl:variable name="padded-hex" select="concat(substring('00000000', 1, 8 - string-length($hex-input)), $hex-input)" />

第二步:把8位十六进制转成64位有符号整数

如果你用的DataPower支持XSLT 2.0(更简单)

XSLT 2.0原生支持64位整数类型,结合xs:hexBinary和xs:long直接转:

<xsl:variable name="hex-binary" select="xs:hexBinary($padded-hex)" />
<xsl:variable name="signed-long" select="xs:long($hex-binary)" />

这段代码先把十六进制字符串转成二进制类型,再直接转成64位有符号整数,一步到位。

要是只能用XSLT 1.0(兼容旧版DataPower)

XSLT 1.0没原生64位整数支持,得自己写模板处理,还要考虑符号位(最高位是8-F的话就是负数)。下面是自定义模板:

<xsl:template name="hex-to-signed-long">
  <xsl:param name="hex" />
  <xsl:param name="pos" select="string-length($hex)" />
  <xsl:param name="result" select="0" />
  <xsl:if test="$pos > 0">
    <xsl:variable name="char" select="substring($hex, $pos, 1)" />
    <xsl:variable name="value">
      <xsl:choose>
        <xsl:when test="$char >= '0' and $char <= '9'"><xsl:value-of select="number($char)" /></xsl:when>
        <xsl:when test="$char >= 'A' and $char <= 'F'"><xsl:value-of select="10 + string-length(substring('ABCDEF', 1, string-length($char) - string-length(translate($char, 'ABCDEF', ''))))" /></xsl:when>
        <xsl:when test="$char >= 'a' and $char <= 'f'"><xsl:value-of select="10 + string-length(substring('abcdef', 1, string-length($char) - string-length(translate($char, 'abcdef', ''))))" /></xsl:when>
      </xsl:choose>
    </xsl:variable>
    <xsl:call-template name="hex-to-signed-long">
      <xsl:with-param name="hex" select="$hex" />
      <xsl:with-param name="pos" select="$pos - 1" />
      <xsl:with-param name="result" select="$result + $value * (16 ^ ($pos - 1))" />
    </xsl:call-template>
  </xsl:if>
  <xsl:if test="$pos = 0">
    <!-- 处理符号位:最高位字符值>=8就是负数 -->
    <xsl:variable name="msb" select="substring($hex, 1, 1)" />
    <xsl:variable name="msb-value">
      <xsl:choose>
        <xsl:when test="$msb >= '8' and $msb <= '9'"><xsl:value-of select="number($msb)" /></xsl:when>
        <xsl:when test="$msb >= 'A' and $msb <= 'F'"><xsl:value-of select="10 + string-length(substring('ABCDEF', 1, string-length($msb) - string-length(translate($msb, 'ABCDEF', ''))))" /></xsl:when>
        <xsl:when test="$msb >= 'a' and $msb <= 'f'"><xsl:value-of select="10 + string-length(substring('abcdef', 1, string-length($msb) - string-length(translate($msb, 'abcdef', ''))))" /></xsl:when>
        <xsl:otherwise><xsl:value-of select="0" /></xsl:otherwise>
      </xsl:choose>
    </xsl:variable>
    <xsl:choose>
      <xsl:when test="$msb-value >= 8">
        <!-- 负数:用补码计算 -->
        <xsl:value-of select="$result - (16^8)" />
      </xsl:when>
      <xsl:otherwise>
        <xsl:value-of select="$result" />
      </xsl:otherwise>
    </xsl:choose>
  </xsl:if>
</xsl:template>

调用模板的方式:

<xsl:variable name="signed-long">
  <xsl:call-template name="hex-to-signed-long">
    <xsl:with-param name="hex" select="$padded-hex" />
  </xsl:call-template>
</xsl:variable>

第三步:把十六进制转成ANSI字符串

其实原VB逻辑是把Long转8位十六进制后,每两位转一个ANSI字符,所以直接用补好的8位十六进制字符串分组转换更高效,不用先转Long再转回十六进制。

XSLT 2.0实现

用xs:unsignedByte转每两位十六进制为字节值,再转成字符:

<xsl:variable name="ansi-string">
  <xsl:for-each select="(1,3,5,7)">
    <!-- 每次取两位十六进制 -->
    <xsl:variable name="two-chars" select="substring($padded-hex, ., 2)" />
    <!-- 转成0-255的字节值 -->
    <xsl:variable name="byte-value" select="xs:unsignedByte(xs:hexBinary($two-chars))" />
    <!-- 转成ANSI字符 -->
    <xsl:value-of select="codepoints-to-string($byte-value)" />
  </xsl:for-each>
</xsl:variable>

XSLT 1.0实现

自定义模板处理每两位十六进制转字符:

<xsl:template name="two-hex-to-ansi">
  <xsl:param name="two-hex" />
  <xsl:variable name="first" select="substring($two-hex, 1, 1)" />
  <xsl:variable name="second" select="substring($two-hex, 2, 1)" />
  <!-- 计算第一位的十进制值 -->
  <xsl:variable name="first-val">
    <xsl:choose>
      <xsl:when test="$first >= '0' and $first <= '9'"><xsl:value-of select="number($first)" /></xsl:when>
      <xsl:when test="$first >= 'A' and $first <= 'F'"><xsl:value-of select="10 + string-length(substring('ABCDEF', 1, string-length($first) - string-length(translate($first, 'ABCDEF', ''))))" /></xsl:when>
      <xsl:when test="$first >= 'a' and $first <= 'f'"><xsl:value-of select="10 + string-length(substring('abcdef', 1, string-length($first) - string-length(translate($first, 'abcdef', ''))))" /></xsl:when>
    </xsl:choose>
  </xsl:variable>
  <!-- 计算第二位的十进制值 -->
  <xsl:variable name="second-val">
    <xsl:choose>
      <xsl:when test="$second >= '0' and $second <= '9'"><xsl:value-of select="number($second)" /></xsl:when>
      <xsl:when test="$second >= 'A' and $second <= 'F'"><xsl:value-of select="10 + string-length(substring('ABCDEF', 1, string-length($second) - string-length(translate($second, 'ABCDEF', ''))))" /></xsl:when>
      <xsl:when test="$second >= 'a' and $second <= 'f'"><xsl:value-of select="10 + string-length(substring('abcdef', 1, string-length($second) - string-length(translate($second, 'abcdef', ''))))" /></xsl:when>
    </xsl:choose>
  </xsl:variable>
  <!-- 计算字节值 -->
  <xsl:variable name="byte-val" select="$first-val * 16 + $second-val" />
  <!-- 输出ANSI字符,disable-output-escaping确保转义字符生效 -->
  <xsl:value-of select="concat('&#x', format-number($byte-val, '00'), ';')" disable-output-escaping="yes" />
</xsl:template>

调用方式:

<xsl:variable name="ansi-string">
  <xsl:call-template name="two-hex-to-ansi">
    <xsl:with-param name="two-hex" select="substring($padded-hex, 1, 2)" />
  </xsl:call-template>
  <xsl:call-template name="two-hex-to-ansi">
    <xsl:with-param name="two-hex" select="substring($padded-hex, 3, 2)" />
  </xsl:call-template>
  <xsl:call-template name="two-hex-to-ansi">
    <xsl:with-param name="two-hex" select="substring($padded-hex, 5, 2)" />
  </xsl:call-template>
  <xsl:call-template name="two-hex-to-ansi">
    <xsl:with-param name="two-hex" select="substring($padded-hex, 7, 2)" />
  </xsl:call-template>
</xsl:variable>

完整XSLT 2.0示例

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <!-- 输出编码设为ISO-8859-1,对应ANSI -->
  <xsl:output method="text" encoding="ISO-8859-1" />
  
  <xsl:template match="/">
    <!-- 输入的十六进制字符串 -->
    <xsl:variable name="hex-input" select="'111'" />
    <!-- 补前导0到8位 -->
    <xsl:variable name="padded-hex" select="concat(substring('00000000', 1, 8 - string-length($hex-input)), $hex-input)" />
    
    <!-- 转换为64位有符号整数 -->
    <xsl:variable name="hex-binary" select="xs:hexBinary($padded-hex)" />
    <xsl:variable name="signed-long" select="xs:long($hex-binary)" />
    <xsl:text>64位有符号整数:</xsl:text>
    <xsl:value-of select="$signed-long" />
    <xsl:text>&#10;</xsl:text>
    
    <!-- 转换为ANSI字符串 -->
    <xsl:variable name="ansi-string">
      <xsl:for-each select="(1,3,5,7)">
        <xsl:variable name="two-chars" select="substring($padded-hex, ., 2)" />
        <xsl:variable name="byte-value" select="xs:unsignedByte(xs:hexBinary($two-chars))" />
        <xsl:value-of select="codepoints-to-string($byte-value)" />
      </xsl:for-each>
    </xsl:variable>
    <xsl:text>ANSI字符串:</xsl:text>
    <xsl:value-of select="$ansi-string" />
  </xsl:template>
</xsl:stylesheet>

注意点

  • 先确认你的DataPower支持的XSLT版本,优先用2.0的方案,代码更简洁。
  • ANSI字符对应ISO-8859-1编码,输出时一定要设置这个编码,不然字符可能显示乱码。
  • XSLT 1.0的符号位处理要注意:8位十六进制的第一个字符如果是8到F(大小写),说明是负数,模板里会自动计算补码得到正确的64位整数。

内容的提问来源于stack exchange,提问作者Ram Adabala

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 19:15:54