Subject: Re: [xsl] Sort problem From: Jeni Tennison <mail@xxxxxxxxxxxxxxxx> Date: Mon, 5 Feb 2001 12:17:50 +0000 |
Hi Mick, > How can I get the result of the 'substring-before' part and the > 'following::word' part to be handled as one entity? There are two ways of going about this. The first is to use the Becker Method to create a string to sort on conditionally. This is a really horrendous thing to use, but if you want to stick with XSLT 1.0 without any extension functions, then it's really your only choice. The Becker Method is based on the fact that if you do: 1 div boolean-condition then you'll get 1 if the boolean condition is true, and infinity if the boolean condition is false. If you use that within a substring: substring(string-value, 1 div boolean-condition) then you will only get the string value if the boolean condition is true: otherwise you get the empty string. So, if you do: concat(substring(value-if-true, 1 div boolean-condition), substring(value-if-false, 1 div not(boolean-condition))) then you can build conditional strings based on boolean conditions. In your example the condition is whether the last character in the word (the context node) is a '-': substring(., string-length()) = '-' If this is true, then you want to concatenate this value (minus the '-') with the value of the next word with a type attribute equal to 'end': concat(substring(., 1, string-length() - 1), following::word[@type = 'end'] If the condition is false, then you just want the value of the word itself. So the complete conditional string is: concat(substring(concat(substring(., 1, string-length() - 1), following::word[@type = 'end']), 1 div (substring(., string-length()) = '-')), substring(., 1 div not(substring(., string-length()) = '-'))) Horrible, isn't it! Anyway, you can use this in your sort: <xsl:for-each select="root/line/word"> <xsl:sort select="concat( substring( concat(substring(., 1, string-length() - 1), following::word[@type = 'end']), 1 div (substring(., string-length()) = '-')), substring(., 1 div not(substring(., string-length()) = '-')))" /> ... </xsl:for-each> By the way, personally I'd separate out the three conditions for the words into separate templates and apply templates rather than using an xsl:choose, but it's probably just a matter of taste. <xsl:template match="word"> <xsl:value-of select="." /> <br /> </xsl:template> <xsl:template match="word[@type = 'end']" /> <xsl:template match="word[substring(., string-length()) = '-']"> <xsl:value-of select="substring(., 1, string-length() - 1)" /> <xsl:value-of select="following::word[@type = 'end']" /> <br /> </xsl:template> The second method is quite a bit cleaner, but it involves using an extension function at the moment (though it won't when XSLT 1.1 is finalised). Basically, you can put together the words that you want within a result tree fragment, then convert that into a node set, and sort that node set. First, create the variable by iterating over the words you're interested in and creating a separate word element for each of them: <xsl:variable name="words"> <xsl:for-each select="root/line/word[not(@type = 'end')]"> <word><xsl:apply-templates select="." /></word> </xsl:for-each> </xsl:variable> Here I'm using the same templates as above to create the relevant word dependent on its structure. Now that you have the words you want to sort on in a result tree fragment, you can turn that into a node set and iterate over it in whatever order you want: <xsl:for-each select="msxsl:node-set($words)/word"> <xsl:sort select="." /> <xsl:value-of select="." /> <br /> </xsl:for-each> Note that to use the msxsl:node-set extension function, you need to declare the MSXML namespace as urn:schemas-microsoft-com:xslt, and you probably want to mark msxsl as an extension element prefix using the extension-element-prefixes attribute on xsl:stylesheet to prevent spurious namespace declarations being added to your result tree. 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] Sort problem, Mick | Thread | Re: [xsl] Sort problem, Dimitre Novatchev |
Re: [xsl] Sort problem, Dimitre Novatchev | Date | Re: [xsl] Sort problem, Dimitre Novatchev |
Month |