Subject: Re: [xsl] How to convert a recursive function to a loop, using XSLT 2.0? From: "Dimitre Novatchev dnovatchev@xxxxxxxxx" <xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx> Date: Sat, 11 May 2019 21:24:58 -0000 |
And to make this more efficient -- clearly O(N), change the XPath expression to this: for $ind in 1 to count($vEnds), $vLastEnd in (0, $vEnds)[$ind], $vThisEnd in $vEnds[$ind] return my:makeString( for $pos in $vLastEnd+1 to $vThisEnd -1 return $vHex2Dec/*[@from = $vBytes[$pos]]/@to/xs:integer(.) ) On Sat, May 11, 2019 at 12:55 PM Dimitre Novatchev <dnovatchev@xxxxxxxxx> wrote: > 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. > > -- 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.
Current Thread |
---|
|
<- Previous | Index | Next -> |
---|---|---|
Re: [xsl] How to convert a recursiv, Dimitre Novatchev dn | Thread | Re: [xsl] How to convert a recursiv, Costello, Roger L. c |
Re: [xsl] How to convert a recursiv, Dimitre Novatchev dn | Date | [xsl] What is the most efficient XP, Costello, Roger L. c |
Month |