我如何在 XSLT2 中按自然顺序用字母和数字对组进行排序?
How do I sort a group, in natural order, with letters and numbers in XSLT2?
我继承了代码,但我不完全理解为什么它不起作用,但我也希望它能做更多事情。明显的问题是 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 方面很薄弱,所以任何指导都将不胜感激。
提前致谢
要先按点之前的字符串按字母数字顺序对数据进行排序,然后按点后的字符串按数字对数据进行排序,您可以使用两个 xsl:sort
s,如下所示:
<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-group
的 group-by="subfield[@code='u']"
的效果是只处理每个 subfield
中具有相同值的第一个。如果您需要所有 subfield
,请使用 xsl:for-each
遍历 current-group()
或首先使用 xsl:for-each
。
您应该可以在 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 has an example, documentation is at http://saxonica.com/html/documentation9.6/extensibility/config-extend/collation/implementing-collation.html.
我继承了代码,但我不完全理解为什么它不起作用,但我也希望它能做更多事情。明显的问题是 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 方面很薄弱,所以任何指导都将不胜感激。
提前致谢
要先按点之前的字符串按字母数字顺序对数据进行排序,然后按点后的字符串按数字对数据进行排序,您可以使用两个 xsl:sort
s,如下所示:
<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-group
的 group-by="subfield[@code='u']"
的效果是只处理每个 subfield
中具有相同值的第一个。如果您需要所有 subfield
,请使用 xsl:for-each
遍历 current-group()
或首先使用 xsl:for-each
。
您应该可以在 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 has an example, documentation is at http://saxonica.com/html/documentation9.6/extensibility/config-extend/collation/implementing-collation.html.