hc0904pcd
asked on
Write a variable number of sort selects?
Trying to sort a list with a custom character-by-character sort.
Sample input:
<items>
<item>abc</item>
<item>a!c</item>
<item>a2c</item>
</items>
Desired output is sorted by letter, then number, then non-alphanumeric (exclamation mark, spaces etc). For each character.
The xsl below, with 3 sort selects per character, works. But it's ugly code, and to process sorting of unknown input I'd need to anticipate potential string-length of up to at least 50 characters....
I was hoping there'd be a way to iterate from $iterator to $length_second_longest_str ing, writing 3 sort selects for each character.
But I can't see how...
<xsl:variable name="alphabet" select="'abcdefghijklmnipq rstuvwxyzA BCDEFGHIJK LMNOPQRSTU VWXYZ'" />
<xsl:variable name="numberic" select="'012345679'" />
<xsl:variable name="alphanumeric" select="concat($alphabet, $numberic)" />
<xsl:variable name="iterator" select="1" />
<xsl:variable name="length_second_longes t_string">
<xsl:for-each select="//item">
<xsl:sort select="string-length(.)" order="descending" data-type="number" />
<xsl:if test="position() = 2">
<xsl:value-of select="string-length(.)"/ >
</xsl:if>
</xsl:for-each>
</xsl:variable>
<xsl:template match="/">
<xsl:for-each select="//item">
<xsl:sort select="number(contains($a lphanumeri c, substring(.,1,1)))" order="descending" data-type="number" />
<xsl:sort select="substring(.,1,1)" data-type="number" order="ascending" />
<xsl:sort select="substring(.,1,1)" data-type="text" order="ascending" />
<xsl:sort select="number(contains($a lphanumeri c, substring(.,2,1)))" order="descending" data-type="number" />
<xsl:sort select="substring(.,2,1)" data-type="number" order="ascending" />
<xsl:sort select="substring(.,2,1)" data-type="text" order="ascending" />
<xsl:sort select="number(contains($a lphanumeri c, substring(.,3,1)))" order="descending" data-type="number" />
<xsl:sort select="substring(.,3,1)" data-type="number" order="ascending" />
<xsl:sort select="substring(.,3,1)" data-type="text" order="ascending" />
<xsl:copy-of select="."/>
</xsl:for-each>
</xsl:template>
All suggestions appreciated.
Sample input:
<items>
<item>abc</item>
<item>a!c</item>
<item>a2c</item>
</items>
Desired output is sorted by letter, then number, then non-alphanumeric (exclamation mark, spaces etc). For each character.
The xsl below, with 3 sort selects per character, works. But it's ugly code, and to process sorting of unknown input I'd need to anticipate potential string-length of up to at least 50 characters....
I was hoping there'd be a way to iterate from $iterator to $length_second_longest_str
But I can't see how...
<xsl:variable name="alphabet" select="'abcdefghijklmnipq
<xsl:variable name="numberic" select="'012345679'" />
<xsl:variable name="alphanumeric" select="concat($alphabet, $numberic)" />
<xsl:variable name="iterator" select="1" />
<xsl:variable name="length_second_longes
<xsl:for-each select="//item">
<xsl:sort select="string-length(.)" order="descending" data-type="number" />
<xsl:if test="position() = 2">
<xsl:value-of select="string-length(.)"/
</xsl:if>
</xsl:for-each>
</xsl:variable>
<xsl:template match="/">
<xsl:for-each select="//item">
<xsl:sort select="number(contains($a
<xsl:sort select="substring(.,1,1)" data-type="number" order="ascending" />
<xsl:sort select="substring(.,1,1)" data-type="text" order="ascending" />
<xsl:sort select="number(contains($a
<xsl:sort select="substring(.,2,1)" data-type="number" order="ascending" />
<xsl:sort select="substring(.,2,1)" data-type="text" order="ascending" />
<xsl:sort select="number(contains($a
<xsl:sort select="substring(.,3,1)" data-type="number" order="ascending" />
<xsl:sort select="substring(.,3,1)" data-type="text" order="ascending" />
<xsl:copy-of select="."/>
</xsl:for-each>
</xsl:template>
All suggestions appreciated.
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
That was exactly the help I needed!
<xsl:variable name="sort_input" select="'aAbBcCdDeEfFgGhHi IjJkKlLmMn NoOpPqQrRs StTuUvVwWx XyYzZ01234 5679 ?!*'" />
<xsl:variable name="sort_output" select="' !*?012345679aAbBcCdDeEfFgG hHiIjJkKlL mMnNoOpPqQ rRsStTuUvV wWxXyYzZ'" />
<xsl:template match="/">
<items>
<standard_sort>
<xsl:for-each select="//item">
<xsl:sort select="." />
<xsl:copy-of select="."/>
</xsl:for-each>
</standard_sort>
<custom_sort>
<xsl:for-each select="//item">
<xsl:sort select="translate(., $sort_input, $sort_output)" data-type="text" order="ascending" />
<xsl:copy-of select="." />
</xsl:for-each>
</custom_sort>
</items>
</xsl:template>
input:
<items>
<item>abc</item>
<item>a!c</item>
<item>a2c</item>
</items>
output:
<items>
<standard_sort>
<item>a!c</item>
<item>a2c</item>
<item>abc</item>
</standard_sort>
<custom_sort>
<item>abc</item>
<item>a2c</item>
<item>a!c</item>
</custom_sort>
</items>
<xsl:variable name="sort_input" select="'aAbBcCdDeEfFgGhHi
<xsl:variable name="sort_output" select="' !*?012345679aAbBcCdDeEfFgG
<xsl:template match="/">
<items>
<standard_sort>
<xsl:for-each select="//item">
<xsl:sort select="." />
<xsl:copy-of select="."/>
</xsl:for-each>
</standard_sort>
<custom_sort>
<xsl:for-each select="//item">
<xsl:sort select="translate(., $sort_input, $sort_output)" data-type="text" order="ascending" />
<xsl:copy-of select="." />
</xsl:for-each>
</custom_sort>
</items>
</xsl:template>
input:
<items>
<item>abc</item>
<item>a!c</item>
<item>a2c</item>
</items>
output:
<items>
<standard_sort>
<item>a!c</item>
<item>a2c</item>
<item>abc</item>
</standard_sort>
<custom_sort>
<item>abc</item>
<item>a2c</item>
<item>a!c</item>
</custom_sort>
</items>
welcome
ASKER