使用符号、字母和数字的 XSLT 自定义排序(O 计为零)

XSLT Custom Sort with Symbols, Letters, and Numbers (O counts as a zero)

我有一个 table,上面有一排零件号。我需要按一系列非常具体的顺序对输出进行排序,但不知道该怎么做

<xsl:apply-templates select="row">
    <xsl:sort select="row/partNumber"/>
</xsl:apply-templates>

正确。我需要它们按以下方式排序:

  1. 符号(特别是斜杠,然后是句点,然后是破折号)
  2. 字母(字母 O 除外)
  3. 数字(字母 O 算作 0)

有人有什么想法吗?

编辑添加: 我正在使用 XSLT 2.0 和 saxon。而部分样本数据是

<row>
    <partNumber>AN931-4-13</partNumber>
</row>
<row>
    <partNumber>AN931.2</partNumber>
</row>
<row>
    <partNumber>AO931</partNumber>
</row>
<row>
    <partNumber>AP417-3</partNumber>
</row>
<row>
    <partNumber>AP417/3</partNumber>
</row>

它应该输出为:

AN931.2
AN931-4-13
AP417/3
AP417-3
AO931

编辑添加: 这是我使用的解决方案。我通过

将规则设置为变量
<xsl:variable name="rules">
     <xsl:text>&lt; '/' &lt; '.' &lt; '-' &lt; a,A &lt; b,B &lt; c,C &lt; d,D &lt; e,E &lt; f,F &lt; g,G &lt; h,H &lt; i,I &lt; j,J &lt; k,K &lt; l,L &lt; m,M &lt; n,N  &lt; p,P &lt; q,Q &lt; r,R &lt; s,S &lt; t,T &lt; u,U &lt; v,V &lt; w,W &lt; x,X &lt; y,Y &lt; z,Z &lt; 0 = o = O &lt; 1 &lt; 2 &lt; 3 &lt; 4 &lt; 5 &lt; 6 &lt; 7 &lt; 8 &lt; 9</xsl:text>
</xsl:variable>

那我就用了

<xsl:sort select="partNumber" collation="http://saxon.sf.net/collation?rules={encode-for-uri($rules)}"/>

我尝试为您的语法构建一些排序规则并将其提供给 Saxon 配置,在以下示例中使用 XQuery 3.1 和 transform 函数以及内联的所有配置数据:

transform(map {
  'source-node' : .,
  'stylesheet-node' : <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                version="3.0"
                xmlns:xs="http://www.w3.org/2001/XMLSchema"
                exclude-result-prefixes="#all"
                expand-text="yes">

    <xsl:output method="html" indent="yes" html-version="5"/>

    <xsl:mode on-no-match="shallow-copy"/>
    
    <xsl:template match="rows">
      <xsl:copy>
        <xsl:apply-templates select="row">
          <xsl:sort select="partNumber" collation="http://example.com/mc1"/>
        </xsl:apply-templates>
      </xsl:copy>
    </xsl:template>

    <xsl:template match="/" name="xsl:initial-template">
        <xsl:next-match/>
    </xsl:template>

</xsl:stylesheet>,
  'vendor-options' : map {
     QName('http://saxon.sf.net/', 'configuration'): 
       <configuration xmlns="http://saxon.sf.net/ns/configuration">
         <collations>
           <collation uri="http://example.com/mc1"
             alphanumeric="yes"
             rules="&lt; a,A &lt; b,B &lt; c,C &lt; d,D &lt; e,E &lt; f,F &lt; g,G &lt; h,H &lt; i,I &lt; j,J &lt; k,K &lt; l,L &lt; m,M &lt; n,N  &lt; p,P &lt; q,Q &lt; r,R &lt; s,S &lt; t,T &lt; u,U &lt; v,V &lt; w,W &lt; x,X &lt; y,Y &lt; z,Z &lt; 0 = o = O &lt; 1 &lt; 2 &lt; 3 &lt; 4 &lt; 5 &lt; 6 &lt; 7 &lt; 8 &lt; 9 &lt; '/' &lt; '.' &lt; '-'"/>           
         </collations>
       </configuration>
  }
}
)?output

为输入

<rows>
<row>
    <partNumber>AN931-4-13</partNumber>
</row>
<row>
    <partNumber>AN931.2</partNumber>
</row>
<row>
    <partNumber>AO931</partNumber>
</row>
<row>
    <partNumber>AP417-3</partNumber>
</row>
<row>
    <partNumber>AP417/3</partNumber>
</row>
</rows>

我得到输出

<rows>
   <row>
      <partNumber>AN931.2</partNumber>
   </row>
   <row>
      <partNumber>AN931-4-13</partNumber>
   </row>
   <row>
      <partNumber>AP417/3</partNumber>
   </row>
   <row>
      <partNumber>AP417-3</partNumber>
   </row>
   <row>
      <partNumber>AO931</partNumber>
   </row>
</rows>

使用 Saxon 11.2 HE,现在还在 https://xqueryfiddle.liberty-development.net/94hwpia 上使用 10.6 HE 在线测试。

我希望,无论您使用什么 Saxon 9 版本,您都可以为其提供一个适当的配置文件,该文件具有类似于或基于上述示例中的适当排序规则。或者,正如您的评论所指出的,您还可以内联规则:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                version="3.0"
                xmlns:xs="http://www.w3.org/2001/XMLSchema"
                exclude-result-prefixes="#all">
                
    <xsl:param name="rules" as="xs:string">&lt; a,A &lt; b,B &lt; c,C &lt; d,D &lt; e,E &lt; f,F &lt; g,G &lt; h,H &lt; i,I &lt; j,J &lt; k,K &lt; l,L &lt; m,M &lt; n,N  &lt; p,P &lt; q,Q &lt; r,R &lt; s,S &lt; t,T &lt; u,U &lt; v,V &lt; w,W &lt; x,X &lt; y,Y &lt; z,Z &lt; 0 = o = O &lt; 1 &lt; 2 &lt; 3 &lt; 4 &lt; 5 &lt; 6 &lt; 7 &lt; 8 &lt; 9 &lt; '/' &lt; '.' &lt; '-'</xsl:param>

    <xsl:output method="xml" indent="yes"/>

    <xsl:mode on-no-match="shallow-copy"/>
    
    <xsl:template match="rows">
      <xsl:copy>
        <xsl:apply-templates select="row">
          <xsl:sort select="partNumber" collation="http://saxon.sf.net/collation?rules={encode-for-uri($rules)}"/>
        </xsl:apply-templates>
      </xsl:copy>
    </xsl:template>

</xsl:stylesheet>