[XSL-LIST Mailing List Archive Home] [By Thread] [By Date] [Recent Entries] [Reply To This Message] Re: xpath for getting file version
Hi Antony, > What is the xpath for getting the latest version? I have tried: > > <xsl:value-of select="versions/version[number(concat(@year, @month, > @day)) > number(concat(../version/@year, ../version/@month, > ../version/@day))]/@name"/> That's quite a complex expression, which makes it hard to work out what's going wrong. Looking at it bit by bit, the expression: ../version/@year returns a node set of all the year attributes of all the versions. When you use concat() and pass a node set as an argument, the node set gets converted to a string. You convert a node set to a string by taking the value of the first node in the node set, so: concat(../version/@year, ../version/@month, ../version/@day) always gives you the date of the *first* version in the list. You go through all the versions comparing their dates to that version, and get a node set of all those that have a later date. Then the xsl:value-of instruction picks the first one of those to give you the result. (Note that if you used the same expression in the use attribute of xsl:key then you'd get the file elements indexed by the names of each of the later versions, not just the first one.) If you had the versions actually giving the date in numerical form, i.e.: <files> <file name="a"> <versions> <version date="20010301" name="test - B"/> <version date="20001203" name="test - A"/> <version date="20010331" name="test - C"/> </versions> </file> </files> then you could do: versions/version[not(@date < ../version/@date)]/@name but as soon as you need to call any functions to compute the values that you need to compare. When it comes down to it, this is a problem of finding a calculated maximum within an XPath. I think you have at least four options. First, you could index the files by all their versions and worry about which is latest later on. So use the key: <xsl:key name="file-version" match="file" use="versions/version" /> and then when you're processing the files that you retrieve using the key, filter out those that have been retrieved through an early version. Second, you could have a two-stage process (either with two stylesheets or using a node-set() extension function to do it all in one stylesheet). In the first pass, construct XML like the above, with a date attribute giving the entire date, and then use the XPath above in the key. Third, you could use an extension function for finding nodes with the highest values based on an expression, if your processor offers one. If you use Saxon, you could do: <xsl:key name="file-version" match="file" use="saxon:highest(versions/version, saxon:expression('concat(@year, @month, @day)'))" /> Finally, you could write your own extension function to find the latest version of a file. With the EXSLT mechanism, it could look like: <func:function name="my:latest-version"> <xsl:for-each select="versions/version"> <xsl:sort select="concat(@year, @month, @day)" data-type="number" order="descending" /> <xsl:if test="position() = 1"> <func:result select="@name" /> </xsl:if> </xsl:for-each> </func:function> (or you could write a recursive function if speed was an issue) In a processor that supports EXSLT - Functions (Saxon or 4XSLT), you could do: <xsl:key name="file-version" match="file" use="my:latest-version()" /> I hope that helps, Jeni --- Jeni Tennison http://www.jenitennison.com/ XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list
|
PURCHASE STYLUS STUDIO ONLINE TODAY!Purchasing Stylus Studio from our online shop is Easy, Secure and Value Priced! Download The World's Best XML IDE!Accelerate XML development with our award-winning XML IDE - Download a free trial today! Subscribe in XML format
|