|
[XSL-LIST Mailing List Archive Home] [By Thread] [By Date] [Recent Entries] [Reply To This Message] Re: A challenge.. Group Periods of Data (1..5, 2..8,
On 5/4/05, Karl Stubsjoen <kstubs@xxxxxxxxx> wrote:
> A challenge, group the following XML into 2 periods. The periods are
> arbitrary, but for this example they happen to be:
> Period 1: 1 - 12
> Period 2: 14 - 30
>
> Expected Result:
> <result>
> <period begins="1" ends="12">
> <B period_begin="1" period_end="5"/>
> <B period_begin="2" period_end="7"/>
> <B period_begin="3" period_end="10"/>
> <B period_begin="4" period_end="12"/>
> </period>
> <period begins="14" ends="30">
> <B period_begin="14" period_end="16"/>
> <B period_begin="16" period_end="20"/>
> <B period_begin="16" period_end="30"/>
> </period>
> </result>
>
> Source XML / Result (sorted)
> <A>
> <B period_begin="1" period_end="5"/>
> <B period_begin="2" period_end="7"/>
> <B period_begin="3" period_end="10"/>
> <B period_begin="4" period_end="12"/>
> <B period_begin="14" period_end="16"/>
> <B period_begin="16" period_end="20"/>
> <B period_begin="16" period_end="30"/>
> </A>
>
> Source XML / Result (un-sorted)
> <A>
> <B period_begin="14" period_end="16"/>
> <B period_begin="2" period_end="7"/>
> <B period_begin="16" period_end="20"/>
> <B period_begin="1" period_end="5"/>
> <B period_begin="4" period_end="12"/>
> <B period_begin="16" period_end="30"/>
> <B period_begin="3" period_end="10"/>
> </A>
Hi Karl,
This has an elegant solution using the f:foldl() function of FXSL.
Here, I'm giving a "first glance" XSLT 2.0 solution without using FXSL.
This transformation:
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="xs"
>
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="A">
<xsl:variable name="vStarting" select=
"*[not(@period_begin/xs:integer(.)
<=
preceding-sibling::*/@period_end/xs:integer(.)
)]">
</xsl:variable>
<xsl:for-each select="$vStarting">
<xsl:variable name="vPos" select="position()"/>
<period start="{@period_begin}"
end="{if ($vPos = last() )
then
max( (. | following-sibling::*)
/@period_end/xs:integer(.)
)
else
max( (. | following-sibling::*)
[. << $vStarting[$vPos + 1]]
/@period_end/xs:integer(.)
)
}"
/>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
when applied on this source xml document (added one more group to yours):
<A>
<B period_begin="1" period_end="5"/>
<B period_begin="2" period_end="7"/>
<B period_begin="3" period_end="10"/>
<B period_begin="4" period_end="12"/>
<B period_begin="14" period_end="16"/>
<B period_begin="16" period_end="20"/>
<B period_begin="16" period_end="30"/>
<B period_begin="32" period_end="33"/>
<B period_begin="33" period_end="38"/>
</A>
produces the wanted result:
<period start="1" end="12"/>
<period start="14" end="30"/>
<period start="32" end="38"/>
Cheers,
Dimitre Novatchev
|
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
|

Cart








