【问题标题】:How do I sort a group, in natural order, with letters and numbers in XSLT2?如何在 XSLT2 中使用字母和数字按自然顺序对组进行排序?
【发布时间】:2019-08-19 23:56:02
【问题描述】:

我继承了代码,但我不完全理解它为什么不起作用,但我也希望它做更多的事情。明显的问题是group-by 永远不会找到一个组,因为它正在寻找的属性始终是每个项目的唯一值。除此之外,我还在寻找自然顺序排序。据我所知,我想我可能需要先按字母对组进行排序,然后按数字对结果进行排序,但我不确定。目前,即使是那里的基本排序也不起作用。现有的 XSLT 代码是:

<xsl:for-each-group select="datafield[@tag='856']" group-by="subfield[@code='u']">
    <xsl:sort select="number(normalize-space(substring-after(subfield[@code='z'], ',')))"/>
    <xsl:copy-of select="."/>
</xsl:for-each-group>

使用这些数据:

<collection>
   <record>
      <datafield ind1="4" ind2="1" tag="856">
         <subfield code="u">https://www.example.com/ride02meys</subfield>
         <subfield code="z">Digital item, v.2</subfield>
      </datafield>
      <datafield ind1="4" ind2="1" tag="856">
         <subfield code="u">https://www.example.com/ride01meys</subfield>
         <subfield code="z">Digital item, v.1</subfield>
      </datafield>
      <datafield ind1="4" ind2="1" tag="856">
         <subfield code="u">https://www.example.com/ride12meys</subfield>
         <subfield code="z">Digital item, v.12</subfield>
   </record>
</collection>

我正在尝试获取以下内容,其中排序为 1、2、12,而不是 1、12、2。

<collection>
   <record>
      <datafield ind1="4" ind2="1" tag="856">
         <subfield code="u">https://www.example.com/ride01meys</subfield>
         <subfield code="z">Digital item, v.1</subfield>
      </datafield>
      <datafield ind1="4" ind2="1" tag="856">
         <subfield code="u">https://www.example.com/ride02meys</subfield>
         <subfield code="z">Digital item, v.2</subfield>
      </datafield>
      <datafield ind1="4" ind2="1" tag="856">
         <subfield code="u">https://www.example.com/ride12meys</subfield>
         <subfield code="z">Digital item, v.12</subfield>
   </record>
</collection>

我承认 XSLT 很弱,所以任何指导都将不胜感激。

谢谢,提前

【问题讨论】:

    标签: xml xslt xslt-2.0 xslt-grouping


    【解决方案1】:

    要先按点前的字符串按字母数字排序数据,然后按点后的字符串按数字排序,您可以像这样使用两个xsl:sorts:

    <xsl:for-each-group select="datafield[@tag='856']" group-by="subfield[@code='u']">
        <xsl:sort select="normalize-space(substring-before(subfield[@code='z'],'.'))" data-type="text"  order="ascending" />
        <xsl:sort select="normalize-space(substring-after(subfield[@code='z'], '.'))" data-type="number" order="ascending" />            
        <xsl:copy-of select="."/>
    </xsl:for-each-group>
    

    这假定点 . 可以用作分隔符。如果分隔符不同,则无法使用此方法。

    附注:
    xsl:for-each-groupgroup-by="subfield[@code='u']" 的效果是,仅处理具有相同值的每个 subfield 中的第一个。如果您需要所有subfields,请使用xsl:for-each 迭代current-group(),或者首先使用xsl:for-each

    【讨论】:

    • 嘿,谢谢!唯一的问题是它并不总是“v.”。该字段变化很大,有时是年,或者“v.”是“vol”。反而。但是,如果它至少按字母顺序排序,然后按数字排序,那将是一个很大的帮助。再次感谢group-by 的信息。
    • 此解决方案仅适用于排序键由字母部分后跟点后跟数字部分组成的特定情况。例如,对于像“Volume 23 Issue 3”这样的键,它不会起作用。
    • @MichaelKay - 虽然我选择了清理示例,但委婉地说,我正在使用的数据高度不一致。所以,即使我痛苦地意识到你到底是多么正确,任何表面上的东西,仍然是一个巨大的帮助。
    【解决方案2】:

    您应该能够在xsl:sort 上使用collation 之类的http://www.w3.org/2013/collation/UCA?lang=en;numeric=yes,如

     <xsl:template match="record">
          <xsl:copy>
            <xsl:for-each-group select="datafield[@tag='856']" group-by="subfield[@code='u']">
                <xsl:sort select="normalize-space(substring-after(subfield[@code='z'], ','))"
                   collation="http://www.w3.org/2013/collation/UCA?lang=en;numeric=yes"/>
                <xsl:copy-of select="."/>
            </xsl:for-each-group>          
          </xsl:copy>
      </xsl:template>
    

    https://xsltfiddle.liberty-development.net/ncdD7nt

    https://www.w3.org/TR/xslt-30/#uca-collations阅读有关排序规则的更多信息。

    对于较旧的 Saxon 9 版本,您可以使用不同的排序规则:

      <xsl:template match="record">
          <xsl:copy>
            <xsl:for-each-group select="datafield[@tag='856']" group-by="subfield[@code='u']">
                <xsl:sort select="normalize-space(substring-after(subfield[@code='z'], ','))"
                   collation="http://saxon.sf.net/collation?lang=en;alphanumeric=yes"/>
                <xsl:copy-of select="."/>
            </xsl:for-each-group>          
          </xsl:copy>
      </xsl:template>
    

    http://xsltransform.net/nbiCsZq 有一个示例,文档位于http://saxonica.com/html/documentation9.6/extensibility/config-extend/collation/implementing-collation.html

    【讨论】:

    • 请注意,这个 UCA 归类 URI 在 XSLT 3.0 中是标准化的,因此所有 XSLT 3.0 处理器都应该提供它。排序规则 URI 在 XSLT 2.0 中可用,但它们没有在不同的处理器之间标准化。
    猜你喜欢
    • 1970-01-01
    • 2019-01-26
    • 1970-01-01
    • 2015-05-17
    • 2021-12-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多