0

(1) My requirement is to convert a DECIMAL INPUT to hexadecimal notation with fixed 8 digits

(2) Convert/Map HEXADECIMAL RESULT to character set by picking 2 HEXADECIMAL characters at a time and append the respective character codes. Please refer to below link for character encoding
https://learn.microsoft.com/en-us/office/vba/language/reference/user-interface-help/character-set-0127
https://learn.microsoft.com/en-us/office/vba/language/reference/user-interface-help/character-set-128255

(3) The final character encoding is showcased as OUTPUT

(4) Can XSLT handle all the special encoding character sets?

DECIMAL INPUT

 <decimal> 
   <input>2<input>
   <input>100<input>
   <input>819<input>
   <input>60<input>
 </decimal>

HEXADECIMAL RESULT

 <input>
   <hex>00000002</hex>
   <hex>00000064</hex>
   <hex>00000333</hex>
   <hex>0000003C</hex>
 </input>

OUTPUT - CHARACTER ENCODING

 <output>
   <charset>    </charset>
   <charset>   d</charset>
   <charset>   3</charset>
   <charset>   <</charset>
 </output>
4
  • 1
    Your question is not clear. What is the expected result of the input example, and what is the logic required to get it? The term "ASCII character encoding" is meaningless to me. Commented Jul 18, 2024 at 17:57
  • It's worth noting that the Unicode character whose codepoint is 2 (your first hex example) is not valid in XML 1.0, so you may need a <xsl:output method="xml" version="1.1"/> in your stylesheet, and you might need to ensure that the XSLT processor is happy to use XML 1.1 (which allows a wider range of acceptable characters than XML 1.0). Commented Jul 21, 2024 at 14:03
  • 1
    Your question still does not make sense. If your expected output is characters then there is no need to convert the decimal values to hexadecimal notation; you can simply use the codepoints-to-string() function to convert the decimal values directly to the corresponding Unicode characters. However, the (decimal) Unicode codepoint of 819 represents the character COMBINING DOUBLE LOW LINE, not the DIGIT THREE that you show. Commented Jul 21, 2024 at 18:11
  • Your clarification that the codepoints in your input are 2 hex digits (8 bits) in length, reference to learn.microsoft.com/en-us/office/vba/language/reference/… and comment about "all the special special encoding character sets" implies to me that the characters whose codepoints are > 127 could be encoded using one of various different "code pages". Those character encodings are not ASCII (which is only a 7 bit encoding) and they may not be Unicode either. Do you know what the code page of the input data is? Commented Jul 21, 2024 at 22:40

3 Answers 3

1

Some of these codes are outside the ASCII range, but if by ASCII you mean Unicode, you could try

<xsl:value-of select="concat('&amp;#x', hex, ';')"
  disable-output-escaping="yes"/>
Sign up to request clarification or add additional context in comments.

1 Comment

Thank You @MichaelKay, this fulfills the need.
0

I am going to take a guess here and assume that your input values are decimal numbers, each representing a string of up to 4 characters, so that for example the string "Char" (which in hexadecimal notation would be represented as 43 68 61 72) is calculated as the decimal value of the combined hexadecimal number 43686172 = 1130914162.

Now, to decode such number back to the original string it is sufficient to do:

XML

<input>
    <decimal>67</decimal>
    <decimal>17256</decimal>
    <decimal>4417633</decimal>
    <decimal>1130914162</decimal>
    <decimal>100</decimal>
    <decimal>51</decimal>
    <decimal>60</decimal>
</input>

XSLT 2.0

<xsl:stylesheet version="2.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:math="http://www.w3.org/2005/xpath-functions/math"
exclude-result-prefixes="math">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>

<xsl:template match="/input">
    <output>
        <xsl:for-each select="decimal">
            <xsl:variable name="codes" select="for $i in 0 to 3 return . idiv math:pow(256, $i) mod 256"/>    
            <charset>
                <xsl:value-of select="codepoints-to-string(reverse($codes[. > 0]))"/>
            </charset>
        </xsl:for-each>
    </output>
</xsl:template>

</xsl:stylesheet>

Result

<?xml version="1.0" encoding="UTF-8"?>
<output>
   <charset>C</charset>
   <charset>Ch</charset>
   <charset>Cha</charset>
   <charset>Char</charset>
   <charset>d</charset>
   <charset>3</charset>
   <charset>&lt;</charset>
</output>

Comments

0

EDIT: this is an answer to the original question which asked how to convert a hex number into a character using XSLT.

I'm leaving my answer here in case it's helpful to someone with that problem, though it's not a very helpful answer to the question as it's subsequently been edited.

Here's an alternative using XSLT 2.0, which I think is supported by IBM DataPower.

XSLT 2.0 includes the codepoints-to-string function which can convert a Unicode codepoint (number) into a string. But the conversion of hex digits to integers is still a long-winded affair (at least, I don't know of an easy way to do it).

<xsl:stylesheet version="2.0" 
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
  xmlns:hex="http://example.com/hex"
  xmlns:xs="http://www.w3.org/2001/XMLSchema">

  <xsl:output method="xml" version="1.1"/>
  
  <xsl:function name="hex:to-integer" as="xs:integer">
    <xsl:param name="hex" as="xs:string"/>
    <xsl:variable name="least-significant-digit"
      select="substring($hex, string-length($hex))"/>
    <xsl:variable name="most-significant-digits" 
      select="substring($hex, 1, string-length($hex) - 1)"/>
    <xsl:variable name="hex-digit-value" select="
      string-length(
        substring-before('0123456789ABCDEF', $least-significant-digit)
      )
    "/>
    <xsl:choose>
      <xsl:when test="$most-significant-digits">
        <xsl:sequence 
          select="$hex-digit-value + 16 * hex:to-integer($most-significant-digits)"/>
      </xsl:when>
      <xsl:otherwise>
        <xsl:sequence select="$hex-digit-value"/>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:function>
  
  <xsl:template match="input">
    <output>
      <xsl:apply-templates/>
    </output>
  </xsl:template>
  
  <xsl:template match="hex">
    <xsl:value-of select="codepoints-to-string(hex:to-integer(.))"/>
  </xsl:template>
  
</xsl:stylesheet>

2 Comments

I'm sorry, but I've updated the problem statement with more accurate information. Please review and let me know if any additional information is required. I'm facing really tough time to debug a 15years old legacy VB.Net code and replicate in DataPower XSLTs. Thank You in adavance.
If your input is actually in decimal format then there's no need to convert it to hexadecimal. Don't assume that the XSLT should use the same procedure as the VB code you're porting. You can just use modulo arithmetic operations with a modulus of 256.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.