Subject: [xsl] XSLT Recursive grouping - can't determine next group From: "Kyle Partridge" <kpartridge@xxxxxxxxxxxx> Date: Tue, 6 Apr 2004 18:19:06 -0400 |
Hi everybody, I'm trying to write a set of templates to do recursive grouping. The xml looks like this: <regions> <region region-id="7" left="180" top="8.25" width="85.5" height="228"> Region 3 </region> <region region-id="4" left="48" top="38.25" width="84.75" height="36"> Region 1 </region> <region region-id="6" left="30" top="104.25" width="84" height="48"> Region 2 </region> <region region-id="8" left="24" top="272.25" width="38.25" height="48"> Region 4 </region> <region region-id="9" left="108" top="278.25" width="38.25" height="60"> Region 5 </region> </regions> The xml I want is this: <regions> <region-set> <region-data-summary region-id="7" left="180" top="8.25" right="265.5" bottom="236.25"/> <region region-id="7" left="180" top="8.25" width="85.5" height="228"> Region 3 </region> <region-data-summary region-id="4" left="48" top="38.25" right="132.75" bottom="74.25"/> <region region-id="4" left="48" top="38.25" width="84.75" height="36"> Region 1 </region> <region-data-summary region-id="6" left="30" top="104.25" right="114" bottom="152.25"/> <region region-id="6" left="30" top="104.25" width="84" height="48"> Region 2 </region> </region-set> <region-set> <region-data-summary region-id="8" left="24" top="272.25" right="62.25" bottom="320.25"/> <region region-id="8" left="24" top="272.25" width="38.25" height="48"> Region 4 </region> <region-data-summary region-id="9" left="108" top="278.25" right="146.25" bottom="338.25"/> <region region-id="9" left="108" top="278.25" width="38.25" height="60"> Region 5 </region> </region-set> </regions> In my XSLT (below), I'm trying to use Jeni Tennison's recursive grouping method (XSLT and XPath on the Edge, pp. 204, 205) - but something's not working because I can't seem to figure out how to determine which region to process next, after I've finished creating my region-set... This code will create the first region-set shown in the desired XML above, no problem. But then I can't figure out how to apply-templates in order to start the node-set gathering process over on region 4 (region-id=8). A region-set ends when the region being tested does not sit "beside" (see xslt template of same name for definition, below) either of the two regions that preceded it. This is triggered by region4 (region-id=8), but after the "item" mode template returns, there is no way for me to know that. I hope this is making some kind of logical sense? Can someone please help shed some light on what I'm doing wrong here? Many thanks, KP <xsl:template match="regions"> <regions> <xsl:apply-templates select="region[1]" mode="group"/> </regions> </xsl:template> <xsl:template match="region" mode="group"> <xsl:variable name="next-region" select="following-sibling::region[1]"/> <xsl:if test="$next-region!=''"> <xsl:variable name="this-beside-next"> <xsl:call-template name="beside"> <xsl:with-param name="region1" select="."/> <xsl:with-param name="region2" select="$next-region"/> </xsl:call-template> </xsl:variable> <xsl:choose> <xsl:when test="$this-beside-next=1"> <region-set> <region-data-summary region-id="{@region-id}" left="{@left}" top="{@top}" right="{@left+@width}" bottom="{@top+@height}"/> <xsl:copy-of select="."/> <region-data-summary region-id="{$next-region/@region-id}" left="{$next-region/@left}" top="{$next-region/@top}" right="{$next-region/@left+$next-region/@width}" bottom="{$next-region/@top+$next-region/@height}"/> <xsl:copy-of select="$next-region"/> <!-- skip straight to testing the region after next-region --> <xsl:apply-templates select="following-sibling::region[2]" mode="item"/> </region-set> </xsl:when> <xsl:otherwise> <!-- HOW DO I KNOW WHICH REGION TO TEST NEXT?? --> </xsl:otherwise> </xsl:choose> </xsl:if> </xsl:template> <xsl:template match="region" mode="item"> <xsl:variable name="this-in-group"> <xsl:variable name="this-beside-comp1"> <xsl:call-template name="beside"> <xsl:with-param name="region1" select="."/> <xsl:with-param name="region2" select="preceding-sibling::region[1]"/> </xsl:call-template> </xsl:variable> <xsl:variable name="this-beside-comp2"> <xsl:call-template name="beside"> <xsl:with-param name="region1" select="."/> <xsl:with-param name="region2" select="preceding-sibling::region[2]"/> </xsl:call-template> </xsl:variable> <xsl:value-of select="number($this-beside-comp1)+number($this-beside-comp2)"/> </xsl:variable> <xsl:choose> <xsl:when test="$this-in-group>0"> <region-data-summary region-id="{@region-id}" left="{@left}" top="{@top}" right="{@left+@width}" bottom="{@top+@height}"/> <xsl:copy-of select="."/> <xsl:apply-templates select="following-sibling::region[1]" mode="item"/> </xsl:when> <xsl:otherwise/> </xsl:choose> </xsl:template> <xsl:template name="in-shadow-of"> <!-- Determine whether or not region1 begins or ends (or is contained) within the area of region2 --> <xsl:param name="region1"/> <xsl:param name="region2"/> <xsl:choose> <!-- EITHER top of region2 >= top of region1 AND the top of region2 <= bottom of region1 --> <xsl:when test="$region2/@top >= $region1/@top and $region2/@top <= ($region1/@top + $region1/@height)"> <xsl:value-of select="number('1')"/> </xsl:when> <!-- OR bottom of region2 >= top of region1 and bottom of region2 <= bottom of region1 --> <xsl:when test="($region2/@top + $region2/@height) >= $region1/@top and ($region2/@top + $region2/@height) <= ($region1/@top + $region1/@height)"> <xsl:value-of select="number('1')"/> </xsl:when> <!-- OR region2 is not within the shadow of region1 --> <xsl:otherwise><xsl:value-of select="number('0')"/></xsl:otherwise> </xsl:choose> </xsl:template> <xsl:template name="beside"> <!-- Determine whether or not region1 and region2 are next to each other --> <xsl:param name="region1"/> <xsl:param name="region2"/> <xsl:variable name="one-covers-two"> <xsl:call-template name="in-shadow-of"> <xsl:with-param name="region1" select="$region1"/> <xsl:with-param name="region2" select="$region2"/> </xsl:call-template> </xsl:variable> <xsl:choose> <xsl:when test="$one-covers-two=1">1</xsl:when> <xsl:otherwise> <xsl:variable name="two-covers-one"> <xsl:call-template name="in-shadow-of"> <xsl:with-param name="region1" select="$region2"/> <xsl:with-param name="region2" select="$region1"/> </xsl:call-template> </xsl:variable> <xsl:choose> <xsl:when test="$two-covers-one=1">1</xsl:when> <xsl:otherwise>0</xsl:otherwise> </xsl:choose> </xsl:otherwise> </xsl:choose> </xsl:template>
Current Thread |
---|
|
<- Previous | Index | Next -> |
---|---|---|
Re: [xsl] Importing multiple XML fi, G. Ken Holman | Thread | [xsl] Namespace question, Mark Lundquist |
RE: [xsl] Comparing grouping techni, Pieter Reint Siegers | Date | RE: [xsl] Comparing grouping techni, Michael Kay |
Month |