xsl-list
[Top] [All Lists]

Re: [xsl] Thorny select: getting surrounding years

2010-10-21 16:29:33
At 2010-10-21 10:12 -1000, Brooks Talley wrote:
I've been wresting with this, and my brain is melting. I need to get a
list of the surrounding years for an item -- zero to two years before,
the item itself, zero to two years after. There may be gaps in the
sequence, in which case I still need two items before and after (if
available).

Sample xml:
...
Desired output (or similar, the select is the hard part):

I couldn't do it in a single select assuming XSLT 1.0 ... if you are using XSLT 2.0 then you can review the below and munge the tests into predicates.

I created a second test file that tries to exercise more of your requirements than did your given test file.

I hope this helps.

. . . . . . . . . .  Ken


T:\ftemp>type brooks.xml
<root>
   <item>
      <id>12345</id>
      <year>2005</year>
   </item>
   <otherYears>
     <item>
        <id>56789</id>
        <year>2001</year>
     </item>
     <item>
        <id>67890</id>
        <year>2002</year>
     </item>
     <item>
        <id>78901</id>
        <year>2003</year>
     </item>
     <item>
        <id>12345</id>
        <year>2005</year>
     </item>
     <item>
        <id>89012</id>
        <year>2006</year>
     </item>
     <item>
        <id>90123</id>
        <year>2008</year>
     </item>
   </otherYears>
</root>
T:\ftemp>type brooks.xsl
<?xml version="1.0" encoding="US-ASCII"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
                version="1.0">

<xsl:output method="text"/>

<xsl:template match="/">
  <xsl:for-each select="*/otherYears/item
                        [id=/*/item/id and year=/*/item/year]">
    <xsl:variable name="before"
                  select="preceding-sibling::*[year >= current()/year - 2]"/>
    <xsl:choose>
      <xsl:when test="count($before) &lt; 2">
<xsl:apply-templates select="preceding-sibling::*[position() &lt; 3]"/>
      </xsl:when>
      <xsl:otherwise>
        <xsl:apply-templates select="$before"/>
      </xsl:otherwise>
    </xsl:choose>
    <xsl:apply-templates select="."/>
    <xsl:variable name="after"
select="following-sibling::*[year &lt;= current()/year +2]"/>
    <xsl:choose>
      <xsl:when test="count($after) &lt; 2">
<xsl:apply-templates select="following-sibling::*[position() &lt; 3]"/>
      </xsl:when>
      <xsl:otherwise>
        <xsl:apply-templates select="$after"/>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:for-each>
</xsl:template>

<xsl:template match="item">
  <xsl:value-of select="year"/> = <xsl:value-of select="id"/>
  <xsl:text>
</xsl:text>
</xsl:template>

</xsl:stylesheet>
T:\ftemp>call xslt brooks.xml brooks.xsl
2002 = 67890
2003 = 78901
2005 = 12345
2006 = 89012
2008 = 90123

T:\ftemp>call xslt brooks2.xml brooks.xsl
2003 = 78901
2004 = 44441
2005 = 12345
2006 = 89012
2007 = 77771
2007 = 77772
2007 = 77773

T:\ftemp>type brooks2.xml
<root>
   <item>
      <id>12345</id>
      <year>2005</year>
   </item>
   <otherYears>
     <item>
        <id>56789</id>
        <year>2001</year>
     </item>
     <item>
        <id>67890</id>
        <year>2002</year>
     </item>
     <item>
        <id>78901</id>
        <year>2003</year>
     </item>
     <item>
        <id>44441</id>
        <year>2004</year>
     </item>
     <item>
        <id>12345</id>
        <year>2005</year>
     </item>
     <item>
        <id>89012</id>
        <year>2006</year>
     </item>
     <item>
        <id>77771</id>
        <year>2007</year>
     </item>
     <item>
        <id>77772</id>
        <year>2007</year>
     </item>
     <item>
        <id>77773</id>
        <year>2007</year>
     </item>
     <item>
        <id>90123</id>
        <year>2008</year>
     </item>
   </otherYears>
</root>
T:\ftemp>rem Done!



--
XSLT/XQuery training:   after http://XMLPrague.cz 2011-03-28/04-01
Vote for your XML training:   http://www.CraneSoftwrights.com/s/i/
Crane Softwrights Ltd.          http://www.CraneSoftwrights.com/s/
G. Ken Holman                 mailto:gkholman(_at_)CraneSoftwrights(_dot_)com
Male Cancer Awareness Nov'07  http://www.CraneSoftwrights.com/s/bc
Legal business disclaimers:  http://www.CraneSoftwrights.com/legal


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

<Prev in Thread] Current Thread [Next in Thread>