如何用XSLT 1.0将两个Muenchian分组合并并按日期排序
解决方案:XSLT 1.0 合并分组并按日期排序
针对你的需求,我会分步骤实现:先通过Muenchian分组处理两个独立事件集合,合并分组结果后按日期排序输出。以下是完整的实现思路和代码:
步骤1:定义Muenchian分组键
首先为两个独立的事件集合(假设是pastevent和futureevent,你可以根据实际节点名调整)定义分组键,按date字段分组:
<xsl:key name="past-events-by-date" match="pastevent" use="date"/> <xsl:key name="future-events-by-date" match="futureevent" use="date"/>
步骤2:获取两个分组的唯一节点
通过generate-id()筛选出每个日期下的第一个节点,得到两个分组后的集合:
<!-- 筛选pastevent的分组节点(每个日期仅保留第一个节点作为分组标识) --> <xsl:variable name="past-group-nodes" select="//pastevent[generate-id() = generate-id(key('past-events-by-date', date)[1])]"/> <!-- 筛选futureevent的分组节点 --> <xsl:variable name="future-group-nodes" select="//futureevent[generate-id() = generate-id(key('future-events-by-date', date)[1])]"/>
步骤3:合并两个分组集合
在XSLT 1.0中使用|运算符合并两个节点集:
<xsl:variable name="merged-groups" select="$past-group-nodes | $future-group-nodes"/>
步骤4:按日期排序并输出
由于XSLT 1.0无法直接对dd/mm/yyyy格式的日期排序,我们需要先将日期转换为yyyy-mm-dd的可排序格式,再进行排序遍历:
<xsl:template match="/"> <html> <body> <h1>All Events Grouped by Date</h1> <xsl:for-each select="$merged-groups"> <!-- 转换日期格式用于排序:dd/mm/yyyy → yyyy-mm-dd --> <xsl:sort select="concat(substring(date, 7, 4), '-', substring(date, 4, 2), '-', substring(date, 1, 2))" data-type="text" order="ascending"/> <div style="margin: 10px 0; padding: 10px; border: 1px solid #ccc;"> <h2>Date: <xsl:value-of select="date"/></h2> <!-- 输出该日期下的所有历史事件 --> <h3>Past Events:</h3> <xsl:for-each select="key('past-events-by-date', date)"> <p>• <xsl:value-of select="../../name"/> - <xsl:value-of select="description"/></p> </xsl:for-each> <!-- 输出该日期下的所有未来事件 --> <h3>Future Events:</h3> <xsl:for-each select="key('future-events-by-date', date)"> <p>• <xsl:value-of select="../../name"/> - <xsl:value-of select="description"/></p> </xsl:for-each> </div> </xsl:for-each> </body> </html> </xsl:template>
完整XSLT代码示例
<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <!-- 定义Muenchian分组键 --> <xsl:key name="past-events-by-date" match="pastevent" use="date"/> <xsl:key name="future-events-by-date" match="futureevent" use="date"/> <xsl:variable name="past-group-nodes" select="//pastevent[generate-id() = generate-id(key('past-events-by-date', date)[1])]"/> <xsl:variable name="future-group-nodes" select="//futureevent[generate-id() = generate-id(key('future-events-by-date', date)[1])]"/> <xsl:variable name="merged-groups" select="$past-group-nodes | $future-group-nodes"/> <xsl:template match="/"> <html> <body> <h1>All Events Grouped by Date</h1> <xsl:for-each select="$merged-groups"> <xsl:sort select="concat(substring(date, 7, 4), '-', substring(date, 4, 2), '-', substring(date, 1, 2))" data-type="text" order="ascending"> </xsl:sort> <div style="margin: 10px 0; padding: 10px; border: 1px solid #ccc;"> <h2>Date: <xsl:value-of select="date"/></h2> <h3>Past Events:</h3> <xsl:for-each select="key('past-events-by-date', date)"> <p>• <xsl:value-of select="../../name"/> - <xsl:value-of select="description"/></p> </xsl:for-each> <h3>Future Events:</h3> <xsl:for-each select="key('future-events-by-date', date)"> <p>• <xsl:value-of select="../../name"/> - <xsl:value-of select="description"/></p> </xsl:for-each> </div> </xsl:for-each> </body> </html> </xsl:template> </xsl:stylesheet>
关键说明
- 如果你的两个分组不是
pastevent和futureevent,只需替换match属性中的节点名即可。 - 日期转换部分需根据你实际的日期格式调整
substring的参数:比如如果日期是mm/dd/yyyy,则转换逻辑应为concat(substring(date, 7, 4), '-', substring(date, 1, 2), '-', substring(date, 4, 2))。 - 合并节点集时,
|运算符会自动去重,所以如果两个分组有相同日期的节点,不会重复出现。
内容的提问来源于stack exchange,提问作者JasonWH
相关产品推荐
相关产品推荐

