Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Convert a hexadecimal number to an integer in XSLT

Tags:

xslt

I need to convert a hexadecimal value to an integer value, how can I do that using XSLT?

For example, if the input is hexadecimal FF, my output should be 255.

like image 351
user1482807 Avatar asked Nov 30 '22 11:11

user1482807


2 Answers

Converting hexadecimal to decimal in pure XSLT 1.0:

<xsl:template name="hex2num">
    <xsl:param name="hex"/>
    <xsl:param name="num" select="0"/>
    <xsl:param name="MSB" select="translate(substring($hex, 1, 1), 'abcdef', 'ABCDEF')"/>
    <xsl:param name="value" select="string-length(substring-before('0123456789ABCDEF', $MSB))"/>
    <xsl:param name="result" select="16 * $num + $value"/>
    <xsl:choose>
        <xsl:when test="string-length($hex) > 1">
            <xsl:call-template name="hex2num">
                <xsl:with-param name="hex" select="substring($hex, 2)"/>
                <xsl:with-param name="num" select="$result"/>
            </xsl:call-template>
        </xsl:when>
        <xsl:otherwise>
            <xsl:value-of select="$result"/>
        </xsl:otherwise>
    </xsl:choose>
</xsl:template>
like image 56
michael.hor257k Avatar answered Dec 16 '22 11:12

michael.hor257k


Edit: Sorry, my bad I just noted the OP asked for hex to decimal and not the other way around.

hexToDecimal template for XSLT-1.0:

<xsl:template name="hexToDecimal">
    <xsl:param name="hex"/>
    <xsl:variable name="dec"
        select="string-length(substring-before('0123456789ABCDEF', substring($hex,1,1)))"/>
    <xsl:choose>
        <xsl:when test="$hex = ''">0</xsl:when>
        <xsl:otherwise>
            <xsl:variable name="rest">
                <xsl:call-template name="hexToDecimal">
                    <xsl:with-param name="hex">
                        <xsl:value-of select="substring($hex,2)"/>
                    </xsl:with-param>
                </xsl:call-template>
            </xsl:variable>
            <xsl:value-of select="$dec * math:power(16, string-length($hex) - 1) + $rest"/>
        </xsl:otherwise>
    </xsl:choose>
</xsl:template>

This needs math:power from exslt http://exslt.org/math/


hexToDecimal function for XSLT-2.0:

<xsl:function name="f:hexToDec">
    <xsl:param name="hex"/>
    <xsl:variable name="dec"
        select="string-length(substring-before('0123456789ABCDEF', substring($hex,1,1)))"/>
    <xsl:choose>
        <xsl:when test="matches($hex, '([0-9]*|[A-F]*)')">
            <xsl:value-of
        select="if ($hex = '') then 0
        else $dec * f:power(16, string-length($hex) - 1) + f:hexToDec(substring($hex,2))"/>
        </xsl:when>
        <xsl:otherwise>
            <xsl:message>Provided value is not hexadecimal...</xsl:message>
            <xsl:value-of select="$hex"/>
        </xsl:otherwise>
    </xsl:choose>
</xsl:function>

<xsl:function name="f:power">
    <xsl:param name="base"/>
    <xsl:param name="exp"/>
    <xsl:sequence
        select="if ($exp lt 0) then f:power(1.0 div $base, -$exp)
                else if ($exp eq 0)
                then 1e0
                else $base * f:power($base, $exp - 1)"
    />
</xsl:function>

Leaving this here, also it was not asked for, it might still be useful.

There is no directly implemented function in xslt, so you would have to write it yourself.

Here's a template for XSLT 1.0:

<xsl:template name="decimalToHex">
    <xsl:param name="dec"/>
    <xsl:if test="$dec > 0">
        <xsl:call-template name="decimalToHex">
            <xsl:with-param name="dec" select="floor($dec div 16)"/>
        </xsl:call-template>
        <xsl:value-of select="substring('0123456789ABCDEF', (($dec mod 16) + 1), 1)"/>
    </xsl:if>
</xsl:template>

You call it like this:

<xsl:call-template name="decimalToHex">
    <xsl:with-param name="dec">4095</xsl:with-param>
</xsl:call-template>

And a function for XSLT 2.0:

<xsl:function name="f:decimalToHex">
    <xsl:param name="dec"/>
    <xsl:if test="$dec > 0">
        <xsl:value-of
            select="f:decimalToHex(floor($dec div 16)),substring('0123456789ABCDEF', (($dec mod 16) + 1), 1)"
            separator=""
        />
    </xsl:if>
</xsl:function>

Which you can call like this:

<xsl:value-of select="f:decimalToHex(4095)"/>

Be aware that you have to declare the namespace for the function in you stylesheet.

like image 24
Tobias Klevenz Avatar answered Dec 16 '22 11:12

Tobias Klevenz