1

给定以下 XML 片段:

<forms>
<FORM lob="BO" form_name="AI OM 10"/>
<FORM lob="BO" form_name="CL BP 03 01"/>
<FORM lob="BO" form_name="AI OM 107"/>
<FORM lob="BO" form_name="CL BP 00 02"/>
<FORM lob="BO" form_name="123 DDE"/>
<FORM lob="BO" form_name="CL BP 00 02"/>
<FORM lob="BO" form_name="AI OM 98"/>
</forms>

我需要按 form_name 的字母顺序对 FORM 节点进行排序,以便将 form_name 中包含“AI OM”的所有表单分组在一起,然后在其中按整数按数字顺序排列(其他表单也是如此)。

form_name 可以是开放季节,因为字母和数字可以按任意顺序排列:

XX ## ##
XX XX ##
XX XX ###
XX XX ## ##
XX ###
XX XXXX
'## XXX
XXX###

我认为需要发生的是字符串需要在字母和数字之间拆分。我想,数字部分可能会被删除任何空格来排序。

鉴于“form_name”格式没有规则,我不知道如何拆分字符串然后涵盖所有排序/分组组合。

我们正在使用 XSLT 2.0。谢谢。

4

3 回答 3

3

这种转变

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>

 <xsl:variable name="vDigits" select="'0123456789 '"/>
 <xsl:variable name="vAlpha" select="'ABCDEFGHIJKLMNOPQRSTUVWXYZ '"/>

 <xsl:template match="/*">
  <forms>
   <xsl:for-each select="FORM">
    <xsl:sort select="translate(@form_name,$vDigits,'')"/>
    <xsl:sort select="translate(@form_name,$vAlpha,'')"
        data-type="number"/>
    <xsl:copy-of select="."/>
   </xsl:for-each>
  </forms>
 </xsl:template>
</xsl:stylesheet>

应用于提供的 XML 文档时

<forms>
    <FORM lob="BO" form_name="AI OM 10"/>
    <FORM lob="BO" form_name="CL BP 03 01"/>
    <FORM lob="BO" form_name="AI OM 107"/>
    <FORM lob="BO" form_name="CL BP 00 02"/>
    <FORM lob="BO" form_name="123 DDE"/>
    <FORM lob="BO" form_name="CL BP 00 02"/>
    <FORM lob="BO" form_name="AI OM 98"/>
</forms>

产生想要的正确结果

<forms>
    <FORM lob="BO" form_name="AI OM 10"/>
    <FORM lob="BO" form_name="AI OM 98"/>
    <FORM lob="BO" form_name="AI OM 107"/>
    <FORM lob="BO" form_name="CL BP 00 02"/>
    <FORM lob="BO" form_name="CL BP 00 02"/>
    <FORM lob="BO" form_name="CL BP 03 01"/>
    <FORM lob="BO" form_name="123 DDE"/>
</forms>

请注意

  1. 两条<xsl:sort>指令实现两阶段排序

  2. XPathtranslate()函数用于生成仅 alpha 排序键或仅数字排序键。

于 2010-10-01T20:28:30.090 回答
0

这个样式表:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="node()|@*">
        <xsl:copy>
            <xsl:apply-templates select="node()|@*"/>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="forms">
        <xsl:apply-templates>
            <xsl:sort select="normalize-space(
                                translate(@form_name,
                                          '0123456789',
                                          ''))"/>
            <xsl:sort select="substring-before(
                                concat(
                                  normalize-space(
                                    translate(@form_name,
                                              translate(@form_name,
                                                        '0123456789 ',
                                                        ''),
                                              '')),
                                  ' '),' ')" data-type="number"/>
            <xsl:sort select="substring-after(
                                normalize-space(
                                  translate(@form_name,
                                            translate(@form_name,
                                                      '0123456789 ',
                                                      ''),
                                            '')),
                                  ' ')" data-type="number"/>
        </xsl:apply-templates>
    </xsl:template>
</xsl:stylesheet>

输出:

<FORM lob="BO" form_name="AI OM 10"></FORM>
<FORM lob="BO" form_name="AI OM 98"></FORM>
<FORM lob="BO" form_name="AI OM 107"></FORM>
<FORM lob="BO" form_name="CL BP 00 02"></FORM>
<FORM lob="BO" form_name="CL BP 00 02"></FORM>
<FORM lob="BO" form_name="CL BP 03 01"></FORM>
<FORM lob="BO" form_name="123 DDE"></FORM>

XSLT 2.0 解决方案:这个样式表

<xsl:stylesheet version="2.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:xs="http://www.w3.org/2001/XMLSchema">
    <xsl:output method="xml" indent="yes"/>
    <xsl:template match="node()|@*">
        <xsl:copy>
            <xsl:apply-templates select="node()|@*"/>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="forms">
        <xsl:apply-templates>
            <xsl:sort select="string-join(tokenize(@form_name,' ')
                                            [not(. castable as xs:integer)],
                                          ' ')"/>
            <xsl:sort select="xs:integer(tokenize(@form_name,' ')
                                            [. castable as xs:integer][1])"/>
            <xsl:sort select="xs:integer(tokenize(@form_name,' ')
                                            [. castable as xs:integer][2])"/>
        </xsl:apply-templates>
    </xsl:template>
</xsl:stylesheet>
于 2010-10-01T20:42:16.110 回答
0

应该注意的是,标记的答案并非在所有情况下都有效。

输入:

<forms>
  <FORM lob="BO" form_name="AA 11 AB"/>
  <FORM lob="BO" form_name="AA AZ 01"/>
</forms>

预期输出:

<forms>
  <FORM lob="BO" form_name="AA AZ 01"/>
  <FORM lob="BO" form_name="AA 11 AB"/>
</forms>

实际输出:

<forms>
  <FORM lob="BO" form_name="AA 11 AB"/>
  <FORM lob="BO" form_name="AA AZ 01"/>
</forms>

如果数字后面允许有字母,则不能在第一个排序键中将它们去掉。

于 2014-05-04T04:04:26.327 回答