Subject: [xsl] Feedback on grouping solution From: "Rick Quatro rick@xxxxxxxxxxxxxx" <xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx> Date: Sat, 26 Oct 2019 17:02:59 -0000 |
Hi All, I have the following input: <?xml version="1.0" encoding="UTF-8"?> <procedure> <title/> <step> <para/> <important/> <figure/> <figure/> </step> <note/> <step> <para/> <figure/> <figure/> <note/> <figure/> </step> <step> <para/> <figure/> <figure/> </step> </procedure> 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 the desired output for the sample input (comments added for clarity): <?xml version="1.0" encoding="UTF-8"?> <procedure> <title/> <para/> <!-- odd --> <important/> <!-- even --> <spacer/> <!-- odd --> <figure/> <!-- even --> <spacer/> <!-- odd --> <figure/> <!-- even --> <note/> <para/> <!-- odd --> <figure/> <!-- even --> <spacer/> <!-- odd --> <figure/> <!-- even --> <note/> <!-- odd --> <figure/> <!-- even --> <para/> <!-- odd --> <figure/> <!-- even --> <spacer/> <!-- odd --> <figure/> <!-- even --> </procedure> Here is my stylesheet. My basic question is: is there a better or more efficient way to do this? I really want to master grouping because it comes up in a lot of my tasks. Thank you for any input or criticism. <?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="local-name(.)"> <xsl:choose> <xsl:when test="current-group()[1][not(self::step)]"> <!-- Single element. --> <xsl:apply-templates select="current-group()[1]"/> </xsl:when> <xsl:otherwise> <!-- step group, process the children. --> <xsl:variable name="elements" select="current-group()/*"/> <xsl:message select="$elements"/> <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: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]"> <xsl:choose> <!-- See where the figure is going to fall in the output. --> <xsl:when test="$positionInOutput mod 2 != 0"> <!-- A spacer to force the figure to the right. --> <spacer/> <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: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: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> Rick
Current Thread |
---|
|
<- Previous | Index | Next -> |
---|---|---|
Re: [xsl] LF and serialize()?, Peter Flynn peter@xx | Thread | Re: [xsl] Feedback on grouping solu, Martin Honnen martin |
Re: [xsl] LF and serialize()?, Peter Flynn peter@xx | Date | Re: [xsl] Feedback on grouping solu, Martin Honnen martin |
Month |