[XSL-LIST Mailing List Archive Home]
[By Thread]
[By Date]
Re: 2 unique lists
Subject: Re: 2 unique lists From: Jeni Tennison <jeni@xxxxxxxxxxxxxxxx> Date: Mon, 07 Aug 2000 19:34:32 +0100 |
Matt, Your two solutions are both just slightly mis-implemented such that neither of them work, for the same basic reason: you are looking at the whole document rather than just the dates for the person you're interested in. First, then: ><xsl:template match="person"> > <xsl:value-of select="@name"/><xsl:text>: </xsl:text> > <xsl:for-each select="date[ not( . = preceding::date )]"> > <xsl:value-of select="."/> > <xsl:if test="not(position()=last())">, </xsl:if> > </xsl:for-each> ></xsl:template> If you look at the dates you're selecting there, you're looking for any date that does not have a value equal to the value of a date that precedes it. Axes all work on the *source* rather than on the *current node list*. Therefore the 'precede' axis is finding all the preceding dates in the document. For 'person2', this includes all the dates for 'person1' - all of the dates are replicated for the second person, so none of the dates are output. In this case, you can change 'preceding' to 'preceding-sibling' and it will work because all the dates that you're interested in have the same parent: <xsl:template match="person"> <xsl:value-of select="@name"/><xsl:text>: </xsl:text> <xsl:for-each select="date[ not( . = preceding-sibling::date )]"> <xsl:value-of select="."/> <xsl:if test="not(position()=last())">, </xsl:if> </xsl:for-each> </xsl:template> Second: ><xsl:key name="thedate" match="date" use="."/> > ><xsl:template match="person"> > <xsl:value-of select="@name"/><xsl:text>: </xsl:text> > <xsl:for-each select="date[generate-id(.) = generate-id(key('thedate',.)[1])]"> > <xsl:value-of select="."/> > <xsl:if test="not(position()=last())">, </xsl:if> > </xsl:for-each> ></xsl:template> Within your key, each of the dates is indexed according to the value of the date. They are *all* indexed in document order, so all the 'Feb2000' dates are grouped together under the same key, *all* of them, whether they are under 'person1' or 'person2'. When you retrieve the first date with the same value using the key, you get the first one that appears *in the document* rather than (again) under the particular person. You can get around this by instead choosing the first of the set of dates (retrieved via the key) that have the same person @name as the current person @name: <xsl:key name="thedate" match="date" use="."/> <xsl:template match="person"> <xsl:value-of select="@name"/><xsl:text>: </xsl:text> <xsl:for-each select="date[generate-id(.) = generate-id(key('thedate',.)[../@name = current()/@name][1])]"> <xsl:value-of select="."/> <xsl:if test="not(position()=last())">, </xsl:if> </xsl:for-each> </xsl:template> Alternatively, you can set the key to use as an index a combined value based on the value of the date and the person's @name, and then retrieve only those dates that have this value: <xsl:key name="thedate" match="date" use="concat(../@name, '::', .)"/> <xsl:template match="person"> <xsl:value-of select="@name"/><xsl:text>: </xsl:text> <xsl:for-each select="date[generate-id(.) = generate-id(key('thedate',concat(../@name, '::', .))[1])]"> <xsl:value-of select="."/> <xsl:if test="not(position()=last())">, </xsl:if> </xsl:for-each> </xsl:template> I hope this helps, Jeni Dr Jeni Tennison Epistemics Ltd * Strelley Hall * Nottingham * NG8 6PE tel: 0115 906 1301 * fax: 0115 906 1304 * email: jeni.tennison@xxxxxxxxxxxxxxxx XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list
Current Thread |
---|
|
<- Previous | Index | Next -> |
---|---|---|
RE: 2 unique lists, Chris Bayes | Thread | Re: 2 unique lists, Matthew Cordes |
Clean data using XSLT, Michal_Mart | Date | Re: Why does this work?, Jeni Tennison |
Month |