Subject: Re: [xsl] Feedback on grouping solution From: "Dimitre Novatchev dnovatchev@xxxxxxxxx" <xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx> Date: Sun, 27 Oct 2019 01:24:16 -0000 |
Actually, we don't need 2-pass processing! Below is a really short and simple *XSLT 1* transformation -- it is just 26 lines -- *40% shorter* than the XSLT 3.0 transformation provided by Martin. Enjoy: <xsl:stylesheet version="1.0" xmlns:xsl=" http://www.w3.org/1999/XSL/Transform"> <xsl:output omit-xml-declaration="yes" indent="yes"/> <xsl:strip-space elements="*"/> <xsl:template match="node()|@*" name="identity"> <xsl:copy> <xsl:apply-templates select="node()|@*"/> </xsl:copy> </xsl:template> <xsl:template match="step"><xsl:apply-templates select="*[1]"/></xsl:template> <xsl:template match="step/*"> <xsl:param name="pAdjustments" select="0"/> <xsl:variable name="vNeedsAdjustment" select="self::figure and (count(preceding-sibling::*) +1 + $pAdjustments) mod 2 = 1"/> <xsl:if test="$vNeedsAdjustment"> <spacer/> </xsl:if> <xsl:call-template name="identity"/> <xsl:apply-templates select="following-sibling::*[1]"> <xsl:with-param name="pAdjustments" select="$pAdjustments + $vNeedsAdjustment"/> </xsl:apply-templates> </xsl:template> </xsl:stylesheet> Cheers, Dimitre On Sat, Oct 26, 2019 at 4:22 PM Dimitre Novatchev dnovatchev@xxxxxxxxx < xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx> wrote: > > Now waiting for Dimitre posting a less "fancy" > > but equally compact XSLT 1 solution :) > > The following is a 48-lines XSLT 2.0 solution (2 passes -- equivalent XSLT > 1.0 solution is easy to produce but will need the vendor:node-set() > extension function). > > Martin's XSLT 3.0 solution is 43 lines when <xsl:stylesheet> and > <xsl:output> are added. So the difference in number of lines is not big -- > 12% and I believe the XSLT 2 solution below is less complex and more easily > understandable. > > Maybe I am biased, but I personally believe that it is better to use the > standard XPath 3 functions fold-left() and fold-right() in the spirit of > functional programming. <xsl:iterate> instead helps people avoid thinking > using the concepts of functional programming. Also, its definition is so > complex that I personally needed more than an hour to find out / construct > what cases of its usage are possible and which are mutually exclusive. > > Here is the transformation: > > <xsl:stylesheet version="2.0" xmlns:xsl=" > http://www.w3.org/1999/XSL/Transform"> > <xsl:output omit-xml-declaration="yes" indent="yes"/> > <xsl:strip-space elements="*"/> > > <xsl:variable name="vPass1Result"><xsl:apply-templates > select="/*"/></xsl:variable> > > <xsl:template match="node()|@*" mode="#default pass2"> > <xsl:copy> > <xsl:apply-templates select="node()|(@* except @stepChild)" > mode="#current"/> > </xsl:copy> > </xsl:template> > > <xsl:template match="/"> > <xsl:apply-templates select="$vPass1Result/*" mode="pass2"/> > </xsl:template> > > <xsl:template match="step"><xsl:apply-templates/></xsl:template> > > <xsl:template match="step/*"> > <xsl:copy> > <xsl:apply-templates select="@*"/> > <xsl:attribute name="stepChild"> > <xsl:number level="any" count="/*/step/*"/> > </xsl:attribute> > <xsl:apply-templates select="node()"/> > </xsl:copy> > </xsl:template> > > <xsl:template match="/*" mode="pass2"> > <xsl:copy> > <xsl:apply-templates select="*[1]" mode="pass2"/> > </xsl:copy> > </xsl:template> > > <xsl:template match="/*/*" mode="pass2"> > <xsl:param name="pAdjustments" select="0"/> > <xsl:variable name="vNeedsAdjustment" select="self::figure and > (count(preceding-sibling::*[@stepChild]) +1 + $pAdjustments) mod 2 = 1"/> > > <xsl:if test="$vNeedsAdjustment"> > <spacer/> > </xsl:if> > <xsl:next-match/> > > <xsl:apply-templates select="following-sibling::*[1]" mode="pass2"> > <xsl:with-param name="pAdjustments" select="$pAdjustments + > (if($vNeedsAdjustment) then 1 else 0)"/> > </xsl:apply-templates> > </xsl:template> > </xsl:stylesheet> > > > Cheers, > Dimitre > > > > On Sat, Oct 26, 2019 at 12:06 PM Martin Honnen martin.honnen@xxxxxx < > xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx> wrote: > >> On 26.10.2019 19:03, Rick Quatro rick@xxxxxxxxxxxxxx wrote: >> >> > I need to process the <step> child elements so that the <figure> >> > elements are always on the "right" (even-numbered position) in the >> > output. Immediate children of the <procedure> do not factor into the >> > odd/even sequence. >> > >> > The first child of each group of adjacent <step> elements starts a new >> > odd/even series. To ensure that the each <figure> is in an even-numbered >> > position, I want to insert a <spacer> element where it is required. >> >> > Here is my stylesheet. My basic question is: is there a better or more >> > efficient way to do this? >> >> I think with XSLT 3 it is possible to use xsl:iterate on the child >> elements of the adjacent steps found by grouping: >> >> <xsl:mode on-no-match="shallow-copy"/> >> >> <xsl:template match="procedure"> >> <xsl:copy> >> <xsl:for-each-group select="*" >> group-adjacent="boolean(self::step)"> >> <xsl:choose> >> <xsl:when test="current-grouping-key()"> >> <xsl:iterate select="current-group()/*"> >> <xsl:param name="position-in-output" >> select="1"/> >> <xsl:apply-templates select="."> >> <xsl:with-param >> name="position-in-output" select="$position-in-output"/> >> </xsl:apply-templates> >> <xsl:next-iteration> >> <xsl:with-param name="position-in-output" >> select="if (self::figure and >> $position-in-output mod 2 = 1) >> then $position-in-output + 2 >> else $position-in-output + >> 1"/> >> </xsl:next-iteration> >> </xsl:iterate> >> </xsl:when> >> <xsl:otherwise> >> <xsl:apply-templates select="current-group()"/> >> </xsl:otherwise> >> </xsl:choose> >> </xsl:for-each-group> >> </xsl:copy> >> </xsl:template> >> >> <xsl:template match="step/figure"> >> <xsl:param name="position-in-output"/> >> <xsl:if test="$position-in-output mod 2 = 1"> >> <spacer/> >> </xsl:if> >> <xsl:next-match/> >> </xsl:template> >> >> >> >> Now waiting for Dimitre posting a less "fancy" but equally compact XSLT >> 1 solution :)
Current Thread |
---|
|
<- Previous | Index | Next -> |
---|---|---|
Re: [xsl] Feedback on grouping solu, Dimitre Novatchev dn | Thread | Re: [xsl] Feedback on grouping solu, Dimitre Novatchev dn |
Re: [xsl] Feedback on grouping solu, Dimitre Novatchev dn | Date | Re: [xsl] Feedback on grouping solu, Dimitre Novatchev dn |
Month |