2010-10-27 220 views
0

给定XML,其中FORMNUMBER只能是数字;从数字开始,然后包含alpha;或遵循一个数字字母数字图案:混合字符串值的字母数字排序:字母数字字母

<FORMSLIST> 
    <FORMS> 
     <FORMNUMBER>3 ABC</FORMNUMBER> 
     <FORMSEQ>99900</FORMSEQ> 
    </FORMS> 
    <FORMS> 
     <FORMNUMBER>12 ABC 45</FORMNUMBER> 
     <FORMSEQ>99900</FORMSEQ> 
    </FORMS> 
    <FORMS> 
     <FORMNUMBER>3 XYZ</FORMNUMBER> 
     <FORMSEQ>99900</FORMSEQ> 
    </FORMS> 
    <FORMS> 
     <FORMNUMBER>18</FORMNUMBER> 
     <FORMSEQ>99900</FORMSEQ> 
    </FORMS> 
    <FORMS> 
     <FORMNUMBER>326</FORMNUMBER> 
     <FORMSEQ>99900</FORMSEQ> 
    </FORMS> 
    <FORMS> 
     <FORMNUMBER>21 B</FORMNUMBER> 
     <FORMSEQ>99900</FORMSEQ> 
    </FORMS> 
    <FORMS> 
     <FORMNUMBER>12 EFG 79</FORMNUMBER> 
     <FORMSEQ>99900</FORMSEQ> 
    </FORMS> 
    <FORMS> 
     <FORMNUMBER>3 ABCD</FORMNUMBER> 
     <FORMSEQ>99900</FORMSEQ> 
    </FORMS> 
</FORMSLIST> 

这是我的样式表(上Alphanumeric sort on mixed string value revisited变化):

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/> 
    <xsl:template match="/"> 
     <xsl:variable name="vAlpha" select="' ABCDEFGHIJKLMNOPQRSTUVWXYZ'"/> 
     <xsl:for-each-group select="FORMSLIST/FORMS" group-by="FORMSEQ"> 
      <xsl:sort select="FORMSEQ" data-type="number"/> 
      <!-- NEED HELP WITH THE FOLLOWING SORT --> 
      <xsl:for-each select="current-group()[(floor(number(FORMNUMBER)) = floor(number(FORMNUMBER))) or (substring-before(FORMNUMBER,' ') and translate(substring-before(FORMNUMBER,' '),'','') = '')]"> 
       <xsl:sort select="translate(FORMNUMBER, $vAlpha, '')" data-type="number"/> 
       <xsl:sort select="substring-after(FORMNUMBER,' ')"/> 
       <xsl:element name="{local-name()}"> 
        <xsl:copy-of select="*"/> 
       </xsl:element> 
      </xsl:for-each> 
      <!-- THIS SORT WORKS AND I DON'T HAVE QUESTIONS ON THIS: ALPHA ONLY FORMS; BEGIN WITH ALPHA AND THEN GO TO NUMERIC...MAY ALSO GO BACK TO ALPHA --> 
      <xsl:for-each select="current-group()[contains($vAlpha,substring(FORMNUMBER,1,1)) or (translate(FORMNUMBER, $vAlpha, '') = '')]"> 
       <xsl:sort select="translate(FORMNUMBER, '', '')"/> 
       <xsl:sort select="translate(FORMNUMBER, $vAlpha, '')" data-type="number"/> 
       <xsl:element name="{local-name()}"> 
        <xsl:copy-of select="*"/> 
       </xsl:element> 
      </xsl:for-each> 
     </xsl:for-each-group> 
    </xsl:template> 
</xsl:stylesheet> 

将所得变换是:

<FORMSLIST> 
    <FORMS> 
     <FORMNUMBER>3 ABC</FORMNUMBER> 
     <FORMSEQ>99900</FORMSEQ> 
    </FORMS> 
    <FORMS> 
     <FORMNUMBER>3 ABCD</FORMNUMBER> 
     <FORMSEQ>99900</FORMSEQ> 
    </FORMS> 
    <FORMS> 
     <FORMNUMBER>3 XYZ</FORMNUMBER> 
     <FORMSEQ>99900</FORMSEQ> 
    </FORMS> 
    <FORMS> 
     <FORMNUMBER>18</FORMNUMBER> 
     <FORMSEQ>99900</FORMSEQ> 
    </FORMS> 
    <FORMS> 
     <FORMNUMBER>21 B</FORMNUMBER> 
     <FORMSEQ>99900</FORMSEQ> 
    </FORMS> 
    <FORMS> 
     <FORMNUMBER>326</FORMNUMBER> 
     <FORMSEQ>99900</FORMSEQ> 
    </FORMS> 
    <FORMS> 
     <FORMNUMBER>12 ABC 45</FORMNUMBER> 
     <FORMSEQ>99900</FORMSEQ> 
    </FORMS> 
    <FORMS> 
     <FORMNUMBER>12 EFG 79</FORMNUMBER> 
     <FORMSEQ>99900</FORMSEQ> 
    </FORMS> 
</FORMSLIST> 

我期望的结果将是在排序中包含'12 ABC 45'和'12 EFG 79'表格(列表首先按开头数字排序):

<FORMSLIST> 
    <FORMS> 
     <FORMNUMBER>3 ABC</FORMNUMBER> 
     <FORMSEQ>99900</FORMSEQ> 
    </FORMS> 
    <FORMS> 
     <FORMNUMBER>3 ABCD</FORMNUMBER> 
     <FORMSEQ>99900</FORMSEQ> 
    </FORMS> 
    <FORMS> 
     <FORMNUMBER>3 XYZ</FORMNUMBER> 
     <FORMSEQ>99900</FORMSEQ> 
    </FORMS> 
    <FORMS> 
     <FORMNUMBER>12 ABC 45</FORMNUMBER> 
     <FORMSEQ>99900</FORMSEQ> 
    </FORMS> 
    <FORMS> 
     <FORMNUMBER>12 EFG 79</FORMNUMBER> 
     <FORMSEQ>99900</FORMSEQ> 
    </FORMS> 
    <FORMS> 
     <FORMNUMBER>18</FORMNUMBER> 
     <FORMSEQ>99900</FORMSEQ> 
    </FORMS> 
    <FORMS> 
     <FORMNUMBER>21 B</FORMNUMBER> 
     <FORMSEQ>99900</FORMSEQ> 
    </FORMS> 
    <FORMS> 
     <FORMNUMBER>326</FORMNUMBER> 
     <FORMSEQ>99900</FORMSEQ> 
    </FORMS> 
</FORMSLIST> 

我已经尝试了许多变化,但似乎无法得到它的工作。

回答

0

在XSLT 2.0中,tokenize(FORMNUMBER,'')返回一个由FORMNUMBER中的空格分隔的令牌序列。因此,您可以使用这些<xsl:sort>元素:

  <xsl:sort select="tokenize(FORMNUMBER, ' ')[1]" data-type="number"/> 
      <xsl:sort select="tokenize(FORMNUMBER, ' ')[2]" /> 
      <xsl:sort select="tokenize(FORMNUMBER, ' ')[3]" data-type="number"/> 

未经测试。但它看起来像它会做你想要的。

+0

太棒了,它的工作!更容易。谢谢 – johkar 2010-10-27 20:32:51

+0

@johkar:cool!很高兴它解决了你的问题。 – LarsH 2010-10-27 20:41:49

+0

+1好答案。 – 2010-10-27 21:10:45