Subject: RE: [xsl] max() of three xsl:number results From: "Michael Kay" <mike@xxxxxxxxxxxx> Date: Fri, 23 Dec 2005 09:20:56 -0000 |
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@xxxxxxxxxxxxxxxxxx] > Sent: 23 December 2005 05:05 > To: xsl-list@xxxxxxxxxxxxxxxxxxxxxx > 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
Current Thread |
---|
|
<- Previous | Index | Next -> |
---|---|---|
[xsl] max() of three xsl:number res, Trevor Nicholls | Thread | [xsl] XSL formatting, Shailesh Shinde |
Re: [xsl] XSL formatting, George Cristian Bina | Date | RE: [xsl] XSL formatting, Shailesh Shinde |
Month |