[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,

Subject: Re: A challenge.. Group Periods of Data (1..5, 2..8, 4..9) (10..12; 10..14
From: "Aron Bock" <aronbock@xxxxxxxxxxx>
Date: Sun, 08 May 2005 03:08:08 +0000
successive following sibling
Oh woops (on the "expected result").  Ya, you are right.  Well, no
worries with the bug, but just thought I'd throw it back out here,
thought maybe there was an obvious easy fix.  It is a "gotcha", but
hopefully with a fix.


If I may, this needs just a trivial change:

From:

<xsl:when test="../B[@period_begin &lt;=$e2 and @period_end &gt; $e2]">

To:

<xsl:when test="following::B[1][@period_begin &lt;=$e2 and @period_end &gt;= $e2]">

I've taken the liberty of using following::B[1] since <B>s are ordered. This should catch unusual cases as well, such as successive Bs with the same begin/end, and Bs with begin=end. For example, applied to:


<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="15" period_end="16"/> <B period_begin="15" period_end="16"/> <B period_begin="16" period_end="16"/> <B period_begin="52" period_end="62"/> </A>

It produces:

<?xml version="1.0" encoding="UTF-8"?>
<result>
 <period ends="12" begins="1">
   <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 ends="16" begins="14">
   <B period_begin="14" period_end="16"/>
   <B period_begin="15" period_end="16"/>
   <B period_begin="15" period_end="16"/>
   <B period_begin="16" period_end="16"/>
 </period>
 <period ends="62" begins="52">
   <B period_begin="52" period_end="62"/>
 </period>
</result>


I'd annotated the poster's original solution, mostly fopr my benefit, but looks like it never made it to the list in its entirety. Perhaps it'll make it this time:




From: "Aron Bock" <aronbock@xxxxxxxxxxx>
Reply-To: xsl-list@xxxxxxxxxxxxxxxxxxxxxx
To: xsl-list@xxxxxxxxxxxxxxxxxxxxxx
Subject: Re: A challenge.. Group Periods of Data (1..5, 2..8, 4..9) (10..12; 10..14
Date: Wed, 04 May 2005 20:53:21 +0000


As they say, those who can, do, and those who can't, teach. Thus perhaps I could annotate the solution below:


From: Karl Stubsjoen <kstubs@xxxxxxxxx>

1)  Variable e2 select.
select="@period_end[. &gt; $e]|$e[. &gt;= current()/@period_end]"

How does the pipe work here and is this only evaluating the current B
element, or evaluating all @period_end(s)?

$e is a passed-in param; so this expression selects either current <B>/@period_end if greater than $e, or simply the passed-in $e if it's equal-or-greater than the current <B>/@period_end. Remember that the pipe, "|", indicates "union", not "or" as in many programming languages.



2)  Right off the bat (first iteration), I don't understand how you
determine the period attribute "ends" value.

It assumes the period ends with the @period_end of the first <B>, until proven wrong further downstream.


3)  Variable g select, what does this get you, the ancestor record?
select="/.."

From what I've picked up on this ng, variables declared without a select attribute are usually expected to contain a scalar value. When initialized with "/..", it is expected to contain a node-set--an empty node-set in this case, since it selects the parent-of-root. root has no parent, so the selected set is empty (to start).


4) The copy of within the element period within the otherwise then the
apply templates rule, it obviously creates the new <period/> element,
but I don't see how your recursive template call inserts the
"members", I don't get how you are preserving the member element of
period.

The <xsl:when test="..."> checks whether thare are any <B> elements which overlap our current begin/end. If so we add the current <B> to an "accumulator" ($g), and recursively call ourselves with the *next* <B>. Note that the input <B>s are sorted by their begin/end--<B> elements that overlap our current <B> must be in the immediately-following vicinity. (Remember that the respondent posted another "tree-walking" strategy a few days ago, related to the issue of finding processing-instructions.)


A more detailed explanation follows:


From: David Carlisle <davidc@xxxxxxxxx>
Reply-To: xsl-list@xxxxxxxxxxxxxxxxxxxxxx
To: xsl-list@xxxxxxxxxxxxxxxxxxxxxx
Subject: Re: A challenge.. Group Periods of Data (1..5, 2..8, 4..9) (10..12; 10..14)
Date: Wed, 4 May 2005 13:03:20 +0100



<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">


<xsl:output indent="yes"/>


<xsl:template match="A">
<result>
<xsl:apply-templates select="B[1]"/>
</result>
</xsl:template>


This kicks off the process with the first <B>


<xsl:template match="B">
<xsl:param name="b" select="@period_begin"/>
<xsl:param name="e" select="@period_end"/>
<xsl:param name="g" select="/.."/>
<xsl:variable name="e2" select="@period_end[. &gt; $e]|$e[. &gt;= current()/@period_end]"/>


The first time around no params are passed in. So $b defaults to @period_begin, $e to @period_end, and $g to an empty set. $e2, the "new end" is calculated as either @period_end (if greater-than the passed-in $e) or simply $e (if it's already equal-or-greater than the current <B>'s @period_end). Of course, the first time around, for the forst <B> as it were, it is simply $e.

So now we're armed with a begin and an end, and if we don't find any more <B>s whose periods intersect or overlap this one, we've just found a period. Testing for overlaps is what the next section does.


<xsl:choose>
<xsl:when test="../B[@period_begin &lt;=$e2 and @period_end &gt; $e2]">
 <xsl:apply-templates select="following-sibling::B[1]">
  <xsl:with-param name="b" select="$b"/>
  <xsl:with-param name="e" select="$e2"/>
  <xsl:with-param name="g" select="$g|."/>
 </xsl:apply-templates>
</xsl:when>

What the test asks is this: are there any <B>s whose @period_begin is less than $e2, and whose @period_end id greater than $e2. Pretty straightforward. The existence of such <B>s implies that those <B>s intersect our current begin/end.


See the diagram below:

b=======$e2 (the current <B>)
........2b======2e
................................3b=======3e


b--e2 is our current period. The 2b--2e pair intersects our period, so we need to extend our currently-known end, $e2, to 2e. We do this by recursively processing the intersecting node, passing in our currently-known limits for $b, and the "end" $e2. We also pass in the current <B> via the param nodeset $g, since our it falls in, and will be subsumed by, the period.


  <xsl:otherwise>
  <period begins="{$b}" ends="{$e2}">
    <xsl:copy-of select="$g|."/>
  </period>


Otherwise, i.e. we have no intersecting <B>s, we have just found a period, so print it out. Remember that $g is the "accumulation" of all <B>s we've seen thus far that fall in this period.

<xsl:apply-templates select="following-sibling::B[1]"/>

Restart the process with the next <B>


</xsl:otherwise>
</xsl:choose>
</xsl:template>





</xsl:stylesheet>



<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>





$ saxon period.xml period.xsl
<?xml version="1.0" encoding="utf-8"?>
<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>
   <period begins="32" ends="38">
      <B period_begin="32" period_end="33"/>
      <B period_begin="33" period_end="38"/>
   </period>
</result>


Regards,

--A

_________________________________________________________________
Express yourself instantly with MSN Messenger! Download today - it's FREE! http://messenger.msn.click-url.com/go/onm00200471ave/direct/01/


Current Thread

PURCHASE STYLUS STUDIO ONLINE TODAY!

Purchasing Stylus Studio from our online shop is Easy, Secure and Value Priced!

Buy Stylus Studio Now

Download The World's Best XML IDE!

Accelerate XML development with our award-winning XML IDE - Download a free trial today!

Don't miss another message! Subscribe to this list today.
Email
First Name
Last Name
Company
Subscribe in XML format
RSS 2.0
Atom 0.3
Site Map | Privacy Policy | Terms of Use | Trademarks
Free Stylus Studio XML Training:
W3C Member
Stylus Studio® and DataDirect XQuery ™are products from DataDirect Technologies, is a registered trademark of Progress Software Corporation, in the U.S. and other countries. © 2004-2013 All Rights Reserved.