Ragulf wrote:
If there is something wrong with this code, I would like to
hear it myself.
<xsl:template
match="Range[number(@Cnt)>number(./previous-sibling/@Cnt) and
number(@Cnt)<value-of(./next-sibling/@Cnt)]">
<xsl:call-template name="IsLocalMaximum"/>
</xsl:template>
<xsl:template
match="Range[not(number(@Cnt)>number(./previous-sibling/@Cnt)
and number(@Cnt)<value-of(./next-sibling/@Cnt))]">
<xsl:choose>
[snip...]
A few comments...
1) Since you're looking for local maxima, I think that instead
of Cnt1 > Cnt0 and Cnt1 < Cnt2 (pardon my simplified references),
you want Cnt1 > Cnt0 and Cnt1 > Cnt2 (note the second comparison
changes the < to >). In other words you want to match Range elements
whose @Cnt is greater than that of both its adjacent siblings, not
between them.
2) A style/maintainability/performance issue...
Since the second template matches every Range element not matched
by the first, you don't need to include that huge complex [not(...)]
predicate.
Just use <xsl:template match="Range">, which will by default have
a lower priority than the first template, and will "catch" every
Range element the first one doesn't match.
3) "previous-sibling", without the ::, means "a child element named
'previous-sibling'". Obviously this isn't what you want.
Also, the axis is called preceding-sibling::.
I would rework your match pattern as:
match="Range[(_at_)Cnt > preceding-sibling::Range[1]/@Cnt and
@Cnt > following-sibling::Range[1]/@Cnt]"
(Note, number() is not really necessary as the < > operators convert
their operands to numbers; all number() does here is make sure that
only the *first*node* of its argument is considered. I used [1]
to take care of that aspect since it's clearer.)
Evgenia, here's a stylesheet that I think does what you want.
It outputs a table showing each Range as a row, with three columns
for the three attributes. The Ranges are in document order.
Each Range that is a local maximum (i.e. @Cnt is greater than that of
the row immediately before or after) is styled in bold.
I treated first and last Range elements as local maxima if
they were greater than their only adjacent sibling.
The table is divided into countries with a row-wide "Country {(_at_)ID}"
cell.
Hopefully this is the kind of thing you were looking for...
Blessings,
Lars
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:template match="/">
<html>
<head>
<style type="text/css">
.localmax {
font-weight: bold;
}
td {
text-align: right;
}
</style>
</head>
<body>
<xsl:apply-templates select="PoketTourList"/>
</body>
</html>
</xsl:template>
<xsl:template match="PoketTourList">
<table border="1">
<xsl:apply-templates select="Country" />
</table>
</xsl:template>
<xsl:template match="Country">
<tr><th colspan="3">Country <xsl:value-of select="@ID" /></th></tr>
<tr>
<th>@PriceFrom</th>
<th>@PriceTo</th>
<th>@Cnt</th>
</tr>
<xsl:apply-templates select="Range" />
</xsl:template>
<xsl:template match="Range">
<xsl:variable name="IsLocalMax"
select="(position() = 1 or @Cnt > preceding-sibling::Range[1]/@Cnt)
and (position() = last()
or @Cnt > following-sibling::Range[1]/@Cnt)" />
<tr>
<xsl:if test="$IsLocalMax">
<xsl:attribute name="class">localmax</xsl:attribute>
</xsl:if>
<td><xsl:value-of select="@PriceFrom" /></td>
<td><xsl:value-of select="@PriceTo" /></td>
<td><xsl:value-of select="@Cnt" /></td>
</tr>
</xsl:template>
</xsl:stylesheet>
XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list