对混合字符串值进行字母数字排序:字母数字 alpha

发布于 2024-09-29 05:26:04 字数 5508 浏览 6 评论 0原文

给定 XML,其中 FORMNUMBER 只能是数字;以数字开头,然后包含字母;或遵循数字字母数字模式:

<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>

这是我的样式表(重新访问混合字符串值的字母数字排序的变体):

<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,' '),' 0123456789','') = '')]">
                <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, ' 0123456789', '')"/>
                <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>

我尝试了多种变体,但似乎无法得到让它工作。

Given XML where FORMNUMBER can be numeric only; begin with numeric and then include alpha; or follow a numeric alpha numeric pattern:

<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>

This is my stylesheet (variation on 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,' '),' 0123456789','') = '')]">
                <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, ' 0123456789', '')"/>
                <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>

The resulting transform is:

<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>

My desired result would be to have the '12 ABC 45' and '12 EFG 79' forms included in the sort like so (list is first sorted by beginning number):

<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>

I have tried numerous variations but can't seem to get it to work.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

放手` 2024-10-06 05:26:04

在 XSLT 2.0 中,tokenize(FORMNUMBER, ' ') 返回一个序列FORMNUMBER 中由空格分隔的标记的数量。因此,您可以使用这些 元素:

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

未经测试。但它看起来就像你想要的那样。

In XSLT 2.0, tokenize(FORMNUMBER, ' ') returns a sequence of the tokens that are separated by a space in FORMNUMBER. So you could use these <xsl:sort> elements:

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

Untested. But it looks like it would do exactly what you want.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文