[XSL-LIST Mailing List Archive Home] [By Thread] [By Date] [Recent Entries] [Reply To This Message] Re: Feedback on grouping solution
Hi Dimitre, Thanks for the follow up. Yes, the children of adjacent step elements have to be treated as one group and that lead me to discover another possibility: the first para in each step in the group has to start on the "left" (an odd-numbered position in the output group). I modified the test input so that the first para in the last step would require a spacer. <?xml version="1.0" encoding="UTF-8"?> <procedure> <title/> <step> <para/> <important/> <figure/> <figure/> </step> <note/> <note/> <step> <para/> <figure/> <figure/> <note/> <figure/> <caution/> </step> <step> <para/> <!-- will need a spacer --> <figure/> <figure/> </step> </procedure> Here is the updated stylesheet: <?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xs" version="2.0"> <xsl:output indent="yes"/> <xsl:template match="/procedure"> <procedure> <!-- Group the children of the procedure, keeping adjacent steps together. --> <xsl:for-each-group select="child::*" group-adjacent="boolean(self::step)"> <xsl:choose> <xsl:when test="current-grouping-key()"> <!-- step group, process the children. --> <xsl:variable name="elements" select="current-group()/*"/> <xsl:call-template name="step-element"> <xsl:with-param name="elements" select="$elements"/> <xsl:with-param name="positionInGroup" select="1"/> <xsl:with-param name="positionInOutput" select="1"/> </xsl:call-template> </xsl:when> <xsl:otherwise> <xsl:apply-templates select="current-group()"/> </xsl:otherwise> </xsl:choose> </xsl:for-each-group> </procedure> </xsl:template> <xsl:template name="step-element"> <xsl:param name="elements"/> <xsl:param name="positionInGroup"/> <xsl:param name="positionInOutput"/> <xsl:variable name="currentElement" select="$elements[$positionInGroup]"/> <xsl:choose> <xsl:when test="$currentElement[self::figure or self::para]"> <xsl:choose> <!-- See where the figure or first para is going to fall in the output. --> <xsl:when test="($currentElement[self::figure] and $positionInOutput mod 2 != 0) or ($currentElement[self::para] and $positionInOutput mod 2 = 0 and not($currentElement/preceding-sibling::*))"> <!-- A spacer to force the figure to the right or the first para in a step to the left. --> <spacer/> <xsl:comment select="$positionInOutput"/> <xsl:call-template name="step-element"> <xsl:with-param name="elements" select="$elements"/> <xsl:with-param name="positionInGroup" select="$positionInGroup"/> <xsl:with-param name="positionInOutput" select="$positionInOutput + 1"/> </xsl:call-template> </xsl:when> <xsl:otherwise> <xsl:apply-templates select="$currentElement"/> <xsl:comment select="$positionInOutput"/> <xsl:if test="$elements[$positionInGroup + 1]"> <xsl:call-template name="step-element"> <xsl:with-param name="elements" select="$elements"/> <xsl:with-param name="positionInGroup" select="$positionInGroup + 1"/> <xsl:with-param name="positionInOutput" select="$positionInOutput + 1"/> </xsl:call-template> </xsl:if> </xsl:otherwise> </xsl:choose> </xsl:when> <xsl:otherwise> <xsl:apply-templates select="$currentElement"/> <xsl:comment select="$positionInOutput"/> <xsl:if test="$elements[$positionInGroup + 1]"> <xsl:call-template name="step-element"> <xsl:with-param name="elements" select="$elements"/> <xsl:with-param name="positionInGroup" select="$positionInGroup + 1"/> <xsl:with-param name="positionInOutput" select="$positionInOutput + 1"/> </xsl:call-template> </xsl:if> </xsl:otherwise> </xsl:choose> </xsl:template> <!-- Identity transform --> <xsl:template match="element()"> <xsl:copy> <xsl:apply-templates select="@*, node()"/> </xsl:copy> </xsl:template> </xsl:stylesheet> Here is the output with comments indicating each element's position within the group in the output. <?xml version="1.0" encoding="UTF-8"?> <procedure> <title/> <para/> <!--1--> <important/> <!--2--> <spacer/> <!--3--> <figure/> <!--4--> <spacer/> <!--5--> <figure/> <!--6--> <note/> <note/> <para/> <!--1--> <figure/> <!--2--> <spacer/> <!--3--> <figure/> <!--4--> <note/> <!--5--> <figure/> <!--6--> <caution/> <!--7--> <spacer/> <!--8--> <para/> <!--9--> <figure/> <!--10--> <spacer/> <!--11--> <figure/> <!--12--> </procedure> Although the two-pass solution is more compact and XSLT 1.0-compatible, it has been useful for me to work through and try to understand the recursion I have to use. Thank you to all who contributed. This is a great list! Rick
|
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
|