[XSL-LIST Mailing List Archive Home] [By Thread] [By Date] [Recent Entries] [Reply To This Message] Re: How to convert a recursive function to a loop, usi
Hi Roger, Besides the obvious grouping solution, here is a short XPath 2.0 (plus some XSLT 2.0) to do this in a non-recursive way. Ideally I would use no XSLT and pure XPath 3 -- taking advantage of XPath 3.0 features such as the let - expression and maps, and also the ability to generate XML as a string and then use the standard parse-xml() function to construct a new XML document, using only XPath. One can also produce an XSLT 1.0 solution, using keys. This XSLT 2.0 transformation: <xsl:stylesheet version="2.0" xmlns:xsl=" http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:my="my:my" exclude-result-prefixes="xs my"> <xsl:output omit-xml-declaration="yes" indent="yes"/> <xsl:variable name="vHex2Dec"> <tr from="48" to="72"/> <tr from="4A" to="74"/> <tr from="69" to="105"/> <tr from="6C" to="108"/> </xsl:variable> <xsl:template match="/"> <xsl:variable name="vBytes" select="/*/Byte"/> <xsl:variable name="vEnds" select="index-of($vBytes, '00')"/> <xsl:sequence select= "for $vLastEnd in (0, $vEnds), $vThisEnd in $vEnds[. > $vLastEnd][1] return my:makeString( for $pos in $vLastEnd+1 to $vThisEnd -1 return $vHex2Dec/*[@from = $vBytes[$pos]]/@to/xs:integer(.) ) "/> </xsl:template> <xsl:function name="my:makeString" as="element()"> <xsl:param name="pCodepoints" as="xs:integer*"/> <string> <xsl:sequence select="codepoints-to-string($pCodepoints)"/> </string> </xsl:function> </xsl:stylesheet> When applied on the provided XML fragment (made a wellformed XML document): <t> <Byte>48</Byte> <Byte>69</Byte> <Byte>00</Byte> <Byte>4A</Byte> <Byte>69</Byte> <Byte>6C</Byte> <Byte>6C</Byte> <Byte>00</Byte> </t> produces the wanted result: <string>Hi</string> <string>Jill</string> Cheers, Dimitre On Fri, May 10, 2019 at 4:20 AM Costello, Roger L. costello@xxxxxxxxx < xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx> wrote: > Hello XSLT experts! > > 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> > > -- Cheers, Dimitre Novatchev --------------------------------------- Truly great madness cannot be achieved without significant intelligence. --------------------------------------- To invent, you need a good imagination and a pile of junk ------------------------------------- Never fight an inanimate object ------------------------------------- To avoid situations in which you might make mistakes may be the biggest mistake of all ------------------------------------ Quality means doing it right when no one is looking. ------------------------------------- You've achieved success in your field when you don't know whether what you're doing is work or play ------------------------------------- To achieve the impossible dream, try going to sleep. ------------------------------------- Facts do not cease to exist because they are ignored. ------------------------------------- Typing monkeys will write all Shakespeare's works in 200yrs.Will they write all patents, too? :) ------------------------------------- Sanity is madness put to good use. ------------------------------------- I finally figured out the only reason to be alive is to enjoy it.
|
PURCHASE STYLUS STUDIO ONLINE TODAY!Purchasing Stylus Studio from our online shop is Easy, Secure and Value Priced! Download The World's Best XML IDE!Accelerate XML development with our award-winning XML IDE - Download a free trial today! Subscribe in XML format
|