xsl-list
[Top] [All Lists]

Re: [xsl] Finding the first among equals using XPath

2006-06-22 09:03:47
At 2006-06-22 16:45 +0100, Peter Riocreux wrote:
I am sure this is a hoary old one, but I could not work out the right
runes to achieve it, nor the right keywords to search for to find an
answer

Well said.

I a have a for-each loop over the W elements. Inside the for-each I
want to select one X with each value of Y that exists within that W.

(data copied below)

So for the above example, for //W[1] I want to get the first and third
or second and third X elements, for //W[2] I want all three X elements
and for //W[3] I want any one of the X elements, but only one of them.

I hope that bit is clear.
..
I want a node-set so I can do a for-each on that, so I would prefer to
find a select specifier based on clever use of axes and predicates.

Two answers are below ... both over a node set ... but the first is the variable-based method which allows one to do grouping directly over subtrees, but requires an <xsl:if> in the loop. The second is using the Muenchian method and gives a pure node set but the subtree distinction achieved through the use of the parent's generated identifier may make those responsible for maintaining it difficult to understand what is going on.

I am stuck with using XSL 1.0

That isn't a stigma to bear.  I'm still being asked to teach XSLT 1.0.

I hope the two approaches below are helpful.

. . . . . . . . . Ken

t:\ftemp>type peter.xml
<V>
 <W>
  <Z/>
      <X Y='0'/>
   <X Y='0'/>
    <X Y='1'/>
  <Z/>
  </W>
 <W>
  <Z/>
     <Z/>
      <X Y='0'/>
    <X Y='1'/>
     <X Y='2'/>
     </W>
  <W>
    <X Y='2'/>
     <X Y='2'/>
      <X Y='2'/>
  <Z/>
     <Z/>
         </W>
</V>

t:\ftemp>type peter.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="V">
  <xsl:for-each select="W">
    <xsl:value-of select="concat('/V/W[',position(),']')"/>
    <xsl:text>
</xsl:text>
    <xsl:variable name="Xs" select="X"/>
    <xsl:for-each select="$Xs">
      <xsl:if test="generate-id(.)=generate-id($Xs[(_at_)Y=current()/@Y][1])">
        <xsl:value-of select="concat('got X/@Y=&quot;',@Y,'&quot;')"/>
        <xsl:text>
</xsl:text>
      </xsl:if>
    </xsl:for-each>
  </xsl:for-each>
</xsl:template>

</xsl:stylesheet>
t:\ftemp>xslt peter.xml peter.xsl con
/V/W[1]
got X/@Y="0"
got X/@Y="1"
/V/W[2]
got X/@Y="0"
got X/@Y="1"
got X/@Y="2"
/V/W[3]
got X/@Y="2"

t:\ftemp>type peter2.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:key name="Xs" match="X" use="concat(generate-id(..),' ',@Y)"/>

<xsl:template match="V">
  <xsl:for-each select="W">
    <xsl:value-of select="concat('/V/W[',position(),']')"/>
    <xsl:text>
</xsl:text>
    <xsl:variable name="Xs" select="X"/>
    <xsl:for-each select="$Xs[generate-id(.)=
            generate-id(key('Xs',concat(generate-id(..),' ',@Y))[1])]">
      <xsl:value-of select="concat('got X/@Y=&quot;',@Y,'&quot;')"/>
      <xsl:text>
</xsl:text>
    </xsl:for-each>
  </xsl:for-each>
</xsl:template>

</xsl:stylesheet>
t:\ftemp>xslt peter.xml peter2.xsl con
/V/W[1]
got X/@Y="0"
got X/@Y="1"
/V/W[2]
got X/@Y="0"
got X/@Y="1"
got X/@Y="2"
/V/W[3]
got X/@Y="2"

t:\ftemp>


--
Registration open for UBL training:    Montréal, Canada 2006-08-07
Also for XSL-FO/XSLT training:    Minneapolis, MN 2006-07-31/08-04
Also for UBL/XML/XSLT/XSL-FO training: Varo,Denmark 06-09-25/10-06
World-wide corporate, govt. & user group UBL, XSL, & XML training.
G. Ken Holman                 mailto:gkholman(_at_)CraneSoftwrights(_dot_)com
Crane Softwrights Ltd.          http://www.CraneSoftwrights.com/s/
Box 266, Kars, Ontario CANADA K0A-2E0    +1(613)489-0999 (F:-0995)
Male Cancer Awareness Aug'05  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>