The data type of $X, $Y, and $Z is in each case document-node(). When you
atomize a document node the result is xdt:untypedAtomic. When you apply
max() to a untypedAtomic value, it is converted to a double, and "1.1.1"
cannot be converted to a double.
Change the variables to strings, and max() will then do a string comparison:
<xsl:variable name="X" as="xs:string">
<xsl:number count="section" level="multiple" />
</xsl:variable>
This also has the advantage that a string is a much simpler object than a
document, so there is less overhead in constructing it and using it.
I would strongly recommend ALWAYS declaring the types of your variables and
parameters in XSLT 2.0. It really makes a big difference to ease of
debugging, especially when you use polymorphic functions like max().
However you still have a problem: the max of "1.2.1" and "1.10.3" is
"1.2.1". In principle you can define a collation that sorts 1.10.3 after
1.2.1, but that depends on the facilities offered by your XSLT processor
(your error message doesn't look like one from Saxon). A more pragmatic
solution might be to use <xsl:number format="00001"/> so that all components
of the section number are fixed-length.
Michael Kay
http://www.saxonica.com/
-----Original Message-----
From: Trevor Nicholls [mailto:trevor(_at_)castingthevoid(_dot_)com]
Sent: 23 December 2005 05:05
To: xsl-list(_at_)lists(_dot_)mulberrytech(_dot_)com
Subject: [xsl] max() of three xsl:number results
Hi
I have a <document> which consists of arbitrarily nested
<section>s of mixed
content. Scattered throughout my document I have <target>
elements. I am
trying to generate a listing which maps each <target> to its nearest
<section>:
a) if a target immediately precedes a section then I want
that section's
location, otherwise
b) I want the closest predecessor section, which may be
1) the section containing the target, or
2) the nearest section which precedes it.
In the following simple example I have given each section a
title which
reflects its location in the structure, and given each target
a label which
does the same.
<!-- ===== XML ===== -->
<document>
<section title="1">
<section title="1.1">
<section title="1.1.1">
<section title="1.1.1.1">
</section>
<target label="1.1.1.1a" />
</section>
<target label="1.1.1.1b" />
</section>
<target label="1.2" />
<section title="1.2">
</section>
<section title="1.3">
<target label="1.3" />
</section>
<para />
</section>
<section title="2">
<target label="2" />
<para />
</section>
<section title="3">
</section>
<target label="3" />
</document>
<!-- ========== -->
The following stylesheet arrives at the numbers I want, viz:
<!-- ===== XSL 2.0 ===== -->
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" />
<xsl:template match="/">
<xsl:apply-templates />
</xsl:template>
<xsl:template match="target">
<xsl:variable name="X">
<xsl:number count="section" level="multiple" />
</xsl:variable>
<xsl:variable name="Y">
<xsl:number select="preceding::section[1]"
count="section" level="multiple" />
</xsl:variable>
<xsl:variable name="Z">
<xsl:choose>
<xsl:when test="following::*[1][self::section]">
<xsl:number select="following::*[1][self::section]"
count="section" level="multiple" />
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="0" />
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:value-of select="@label" />
<xsl:text> X</xsl:text><xsl:value-of select="$X">
<xsl:text> Y</xsl:text><xsl:value-of select="$Y">
<xsl:text> Z</xsl:text><xsl:value-of select="$Z">
<xsl:text>
</xsl:text>
</xsl:template>
<!-- ========== -->
When I apply this to the example XML above I get:
1.1.1.1a X1.1.1 Y1.1.1.1 Z0
1.1.1.1b X1.1 Y1.1.1.1 Z0
1.2 X1 Y1.1.1.1 Z1.2
1.3 X1.3 Y1.2 Z0
2 X2 Y1.3 Z0
3 X Y3 Z0
Clearly what I want is the (lexically) greatest value out of
X, Y and Z.
But when I replace the target template's output with the
following lines:
<xsl:value-of select="@label" />
<xsl:text> max </xsl:text>
<xsl:value-of select="max(($X,$Y,$Z))" />
<xsl:text>
</xsl:text>
I get an error:
Error in XPath 2.0 expression Invalid lexical value - '1.1.1'
What am I doing wrong?
Thanks
Trevor
--~------------------------------------------------------------------
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>
--~--
--~------------------------------------------------------------------
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>
--~--