xsl-list
[Top] [All Lists]

Re: A challenge.. Group Periods of Data (1..5, 2..8, 4..9) (10..12; 10..14)

2005-05-03 14:42:16
Dimitre:

*weeping* I am not able to transform with XSLT2 : (
Do you have an "elegant" XSLT1 solution?

Karl

On 5/3/05, Dimitre Novatchev <dnovatchev(_at_)gmail(_dot_)com> wrote:
On 5/4/05, Karl Stubsjoen <kstubs(_at_)gmail(_dot_)com> 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(.)
        &lt;=
          preceding-sibling::*/@period_end/xs:integer(.)
          )]">
   </xsl:variable>

   <xsl:for-each select="$vStarting">
     <xsl:variable name="vPos" select="position()"/>
     <period start="{(_at_)period_begin}"
          end="{if ($vPos = last() )
                then
                   max( (. | following-sibling::*)
                          /@period_end/xs:integer(.)
                       )
                else
                   max( (. | following-sibling::*)
                              [. &lt;&lt; $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

--~------------------------------------------------------------------
XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list
To unsubscribe, go to: http://lists.mulberrytech.com/xsl-list/
or e-mail: 
<mailto:xsl-list-unsubscribe(_at_)lists(_dot_)mulberrytech(_dot_)com>
--~--



--~------------------------------------------------------------------
XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list
To unsubscribe, go to: http://lists.mulberrytech.com/xsl-list/
or e-mail: <mailto:xsl-list-unsubscribe(_at_)lists(_dot_)mulberrytech(_dot_)com>
--~--