Presuming your input has been validated so that only proper hex
values for XML Unicode characters occur inside <Byte>, why not just
treat it as a sequence of codepoints?
<xsl:variable name="numSeq"
select=".//Byte/text()/xs:integer(f:hexToDec(.))"
as="xs:integer+"/>
<xsl:variable name="codepoints"
select="for $n in $numSeq return
if ( $n eq 0 )
then 9216
else $n" as="xs:integer+"/>
<xsl:variable name="string" select="codepoints-to-string($codepoints )"/>
<xsl:for-each select="tokenize( $string,'␀')">
<String><xsl:value-of select="."/></String>
</xsl:for-each>
Note that NULL = 0 = � is converted to SYMBOL FOR NULL = 9216 =
␀ because NULL is not a valid XML character. You could use
any character that is guaranteed not to occur in the input.
You would need to write a hex-to-integer converter, or grab one off
StackOverflow
This would not work of course, if <Byte> represented actual bytes
rather than characters. (I.e., if EURO SIGN were represented as
<Byte>E2</Byte><Byte>82</Byte><Byte>AC</Byte> instead of
<Byte>20AC</Byte>.)
My input file consists of a sequence (sourceSeq) of <Byte> elements
representing a sequence of null-terminated strings. I want to
create a function that returns a sequence of <String> elements. For
example, with this sourceSeq:
<Byte>48</Byte>
<Byte>69</Byte>
<Byte>00</Byte>
<Byte>4A</Byte>
<Byte>69</Byte>
<Byte>6C</Byte>
<Byte>6C</Byte>
<Byte>00</Byte>
the function should return:
<String>Hi</String>
<String>Jill</String>
The strings are of variable length.
I do not know how many null-terminated strings are in sourceSeq.
However, I do know the total number (total-size) of <Byte> elements
within sourceSeq containing the null-terminated strings.
Below is a recursive way to implement the function. Unfortunately,
total-size can be quite large, which means the function recurses
many times, resulting in a "Too many nested function calls" error.
Is there an iterative way to implement the function? /Roger
<xsl:function name="f:make-string-table-entries" as="element(String)*">
<xsl:param name="total-size" as="xs:integer" />
<xsl:param name="current-size" as="xs:integer" />
<xsl:param name="current-position" as="xs:integer" />
<xsl:param name="sourceSeq" as="element(Byte)*" />
<xsl:choose>
<xsl:when test="$current-size ge $total-size" />
<xsl:otherwise>
<xsl:variable name="string"
select="f:make-element-from-null-terminated-string('String',
$current-position, $sourceSeq)" as="element(String)"/>
<xsl:sequence select="$string" />
<xsl:variable name="length" select="string-length($string/text())
+ 1"/> <!-- add 1 for the null byte -->
<xsl:sequence select="f:make-string-table-entries($total-size,
xs:integer($current-size+$length), xs:integer($current-position+$length),
$sourceSeq)" />
</xsl:otherwise>
</xsl:choose>
</xsl:function>
--
Syd Bauman, NRP (he/him/his)
Senior XML Programmer/Analyst
Northeastern University Women Writers Project
s(_dot_)bauman(_at_)northeastern(_dot_)edu or
Syd_Bauman(_at_)alumni(_dot_)Brown(_dot_)edu
--~----------------------------------------------------------------
XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list
EasyUnsubscribe: http://lists.mulberrytech.com/unsub/xsl-list/1167547
or by email: xsl-list-unsub(_at_)lists(_dot_)mulberrytech(_dot_)com
--~--