xslt - XSLT 跨节点和文本排序
问题描述
我正在尝试查找、排序和输出一串版权年份。我有一些工作代码,但我发现我的一些年与其他年不在同一个标签中。
最初,我认为我所有的岁月都在以下标签中:<copyright-year>2020</copyright-year>
,请参阅下面的一些工作代码来查找、排序和输出这些。
我刚刚发现我的一些版权年份是这样的:<copyright-statement>© 2017 Company. All rights reserved.</copyright-statement>
.
我可以使用//copyright-statement/substring(.,3,4)
. 但是,当我尝试搜索这两种类型时:<xsl:for-each-group select="//copyright-year|copyright-statement/substring(., 3, 4)" group-by="text()">
,它会给出以下警告:
单据排序器需要的item类型是node();提供的表达式 ((./copyright-statement)/(fn:substring(...))) 具有项目类型 xs:string。仅当提供的值是空序列时,表达式才能成功。
而且显然行不通。知道如何合并这两组年份以获得:<output>2020, 2019, 2017</output>
?
示例 XML
<?xml version="1.0" encoding="UTF-8"?>
<book>
<book-meta>
<copyright-year>2020</copyright-year>
</book-meta>
<body>
<book-part>
<book-part-meta>
<copyright-year>2019</copyright-year>
</book-part-meta>
</book-part>
</body>
<back>
<copyright-statement>© 2017 Company. All rights reserved.</copyright-statement>
</back>
</book>
示例 XSLT
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="xs"
version="2.0">
<xsl:template match="book">
<xsl:variable name="years">
<xsl:for-each-group select="//copyright-year" group-by="text()">
<xsl:sort select="." order="descending"/>
<xsl:value-of select="."/><xsl:if test="position() != last()"><xsl:text>, </xsl:text></xsl:if>
</xsl:for-each-group>
</xsl:variable>
<output><xsl:value-of select="$years"/></output>
</xsl:template>
</xsl:stylesheet>
解决方案
您使用哪个版本的 XSLT 处理器?XSLT 3 有一个排序功能
<xsl:value-of select="reverse(sort(distinct-values((//copyright-year/xs:integer(.), //copyright-statement/xs:integer(substring(.,3,4))))))" separator=", "/>
https://xsltfiddle.liberty-development.net/bwdwsd
=>
使用新的箭头运算符可能更容易阅读:
<xsl:value-of
select="(//copyright-year/xs:integer(.), //copyright-statement/xs:integer(substring(.,3,4)))
=> distinct-values()
=> sort()
=> reverse()"
separator=", "/>
https://xsltfiddle.liberty-development.net/bwdwsd/2
但总的来说,您需要的步骤是简单地确保您使用原子值,例如xs:integer
s 多年来似乎是正确的值。我认为在 XSLT 2 中我会包装perform-sort
成一个函数:
<xsl:function name="mf:sort" as="item()*">
<xsl:param name="input" as="item()*"/>
<xsl:perform-sort select="$input">
<xsl:sort order="descending"/>
</xsl:perform-sort>
</xsl:function>
<xsl:template match="book">
<xsl:value-of select="mf:sort(distinct-values((//copyright-year/xs:integer(.), //copyright-statement/xs:integer(substring(.,3,4)))))" separator=", "/>
</xsl:template>
推荐阅读
- python - 获得一条直线上的所有点进行技术分析?
- mysql - 您的 SQL 语法有错误;检查与您的 MySQL 服务器版本相对应的手册以获取正确的语法解决方案:
- html - React / Gatsby - 根据屏幕大小渲染不同的组件
- reactjs - onClick 在 Firefox 上不工作 - 在 Chrome 上工作
- anaconda - 错误 conda.core.link:_execute(698): 安装包 'defaults::qt-5.9.7-vc14h73c81de_0' 时出错
- .htaccess - .htaccess 删除查询参数
- python - Python 语音识别无法识别我的声音
- javascript - 从 facebook messenger 获取 FB Access 令牌/OAuth 数据
- javascript - Uncaught (in promise) TypeError: this is undefined
- c# - 忽略插入字符串 C#、SQL Server 中的引号