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_string, writing 3 sort selects for each character.
But I can't see how...


<xsl:variable name="alphabet" select="'abcdefghijklmnipqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'" />
<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_longest_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($alphanumeric, 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($alphanumeric, 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($alphanumeric, 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.
LVL 6
hc0904pcdAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Geert BormansInformation ArchitectCommented:
Though I don't grasp the complete impact of what you are doing, I am pretty convinced you can just do this with one sort, not datatyped as number but datatyped on text.
What you need to do is remap the characters with translate() to the expected behaviour

this could be something like this
 <xsl:sort select="translate(.,'0123456789abcdABCD?./!', '?/.!aAbBcCdD0123456789')" order="descending" data-type="text" />

this is ofcourse just an example, but on remapping each character in your input onto a different character  you control the exact sort order per character

I don't know which behaviour you want and what your current processor does
In XSLT1 you depend on the sort of the underlying technology (could be java, .net, ...)
In XSLT2 you have a concpt of collations that help you to redefine sort behaviour.
That is more efficient, but programming a collation is not exactly easier than using translate to tweek

translate is key
here is how it works
each character in the first argument that is found at a location 'n' in the second argument gets replaced by the character at location 'n' in the third argument

note that numbers play their part in the sorting as text, unless you cast them

0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
hc0904pcdAuthor Commented:
thank you :)
0
hc0904pcdAuthor Commented:
That was exactly the help I needed!


<xsl:variable name="sort_input"  select="'aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ012345679 ?!*'" />
<xsl:variable name="sort_output" select="' !*?012345679aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ'" />      
<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>
0
Geert BormansInformation ArchitectCommented:
welcome
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Web Languages and Standards

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.