Subject: Re: [xsl] RE: grouping content From: Jeni Tennison <mail@xxxxxxxxxxxxxxxx> Date: Fri, 6 Apr 2001 20:38:07 +0100 |
Hi Gavin, > Now when i do that, for some reason if i try: > > <xsl:template match="World/NorthAmerica/US"> > I cannot just have: > <xsl:for-each select="[@Area and > generate-id(.)=generate-id(key('LocationGroups',@Area))]"> > > That returns an error Square brackets in an expression indicate a *predicate*. A predicate is a test on a node set - it's used to filter in a subset of the node set, the ones for which the test returns true. The expression in the above isn't a legal XPath expression - you haven't said what node set the predicate should be filtering. That's why it returns an error. > So I tried removing the []'s, that still returns an error. XSLT processors always expect you to specify a *node set* in a select attribute. If you remove the []s in the above, you're left with a *boolean* expression. The XSLT processor can't iterate over true() or false(), so it returns the error. I think that you intended to do: <xsl:for-each select="Location[@Area and generate-id(.)=generate-id(key('LocationGroups',@Area))]"> ... </xsl:for-each> In other words, iterate over the Location elements that: (a) have an 'Area' attribute and (b) that are the first returned by the 'LocationGroups' key with that Area In your second problem, assuming you don't know all the Areas and Types in advance, you need multi-level keys to allow you to quickly get the Location elements for a particular Area or of a particular Type in a particular Area: <xsl:key name="locs-by-area" match="Location" use="@Area" /> <xsl:key name="locs-by-area-and-type" match="Location" use="concat(@Area, ':', @Type)" /> In the template matching the US, then you can firstly select the Location elements with unique Areas, and then select those with unique Areas and Types, and finally select the relevant Rural or Urban Location: <xsl:template match="US"> <!-- iterate over the Location elements with unique Areas --> <xsl:for-each select="Location[generate-id() = generate-id(key('locs-by-area', @Area))]"> <!-- output a line giving the Area --> <xsl:value-of select="@Area" /><br /><br /> <!-- iterate over the Location elements with this Area, but only those with unique Types --> <xsl:for-each select="key('locations-by-area', @Area)[generate-id() = generate-id(key('locs-by-area-and-type', concat(@Area, ':', @Type))]"> <!-- output a line giving the Type --> <xsl:value-of select="@Type" /><br /> <!-- create a variable to hold the Locations with that Type in that Area --> <xsl:variable name="locations" select="key('locs-by-area-and-type', concat(@Area, ':', @Type)" /> <xsl:text>Rural: </xsl:text> <!-- give the value of the Location with Rural Scope --> <xsl:value-of select="$locations[@Scope = 'Rural']/@value" /> <br /> <xsl:text>Urban: </xsl:text> <!-- give the value of the Location with Urban Scope --> <xsl:value-of select="$locations[@Scope = 'Urban']/@value" /> <br /> </xsl:for-each> </xsl:for-each> </xsl:template> You can do this through applying templates instead, if you prefer that style: <xsl:template match="US"> <!-- iterate over the Location elements with unique Areas --> <xsl:apply-templates mode="area-group" select="Location[generate-id() = generate-id(key('locs-by-area', @Area))]" /> </xsl:template> <xsl:template match="Location" mode="area-group"> <!-- output a line giving the Area --> <xsl:value-of select="@Area" /><br /><br /> <!-- iterate over the Location elements with this Area, but only those with unique Types --> <xsl:apply-templates mode="area-and-type-group" select="key('locations-by-area', @Area)[generate-id() = generate-id(key('locs-by-area-and-type', concat(@Area, ':', @Type))]"> </xsl:template> <xsl:template match="Location" mode="area-and-type-group"> <!-- output a line giving the Type --> <xsl:value-of select="@Type" /><br /> <!-- create a variable to hold the Locations with that Type in that Area --> <xsl:variable name="locations" select="key('locs-by-area-and-type', concat(@Area, ':', @Type)" /> <!-- apply templates to the location with Rural scope --> <xsl:apply-templates select="$locations[@Scope = 'Rural']" /> <!-- apply templates to the location with Urban scope --> <xsl:apply-templates select="$locations[@Scope = 'Urban']" /> </xsl:template> <xsl:template match="Location"> <xsl:value-of select="@Scope" />: <xsl:value-of select="@value" /> <br /> </xsl:template> I hope that helps, Jeni --- Jeni Tennison http://www.jenitennison.com/ XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list
Current Thread |
---|
|
<- Previous | Index | Next -> |
---|---|---|
[xsl] RE: grouping content, Gavin Myers | Thread | [xsl] tracking info for marketing w, Turner, Althea |
[xsl] tracking info for marketing w, Turner, Althea | Date | [xsl] Variable: true or false, Tom Gilbert |
Month |