首页 > 解决方案 > 如何在 XSLT 转换中对结果进行排序?

问题描述

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

xslt是否可以在将结果写入输出流之前对转换结果进行排序?

我的目标是 1)将以下 xml 转换为 csv,2)<person><personNode>.

示例:在下面,最后一个人节点仅包含 1 个人。因此,我想在最终输出中的所有结果之上对这个人进行排序。

然后,应打印所有已在具有 2 人的节点中的人。然后是 3...,然后是 N。

源.xml:

<personNodes>
    <personNode>
        <person>
            <id>1</id>        
            <name>john</name>
        </person>
        <person>
            <id>11</id>        
            <name>doe</name>
        </person>
    </personNode>
    <personNode>
        <person>
            <id>2</id>        
            <name>jane</name>
        </person>
    </personNode>
</personNodes>

转型:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="3.0"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:xs="http://www.w3.org/2001/XMLSchema">
    <xsl:output method="text" omit-xml-declaration="yes" indent="no"/>

    <xsl:mode on-no-match="shallow-skip"/>

    <xsl:template match="personNodes">
        <xsl:for-each select="personNode">
            <xsl:for-each select="person">
                <xsl:value-of select="concat(id, ';', name, '&#10;')"/>
            </xsl:for-each>
        </xsl:for-each>
    </xsl:template>
</xsl:stylesheet>

结果:

1;john
11;doe
2;jane

想要的结果:

#person from 1-person node
2;jane
#persons from 2-person nodes
1;john
11;doe
#persons from 3-person nodes
...
#persons from N-person nodes

这有可能吗,因为我只是将结果打印到输出流<xsl:value-of>?也许我必须在maporlist变量中收集 csv 行,然后在结束循环时再次打印到输出?

标签: xmlxsltsaxon

解决方案


当然使用xsl:sort

<xsl:template match="personNodes">
    <xsl:for-each select="personNode">
        <xsl:sort select="count(person)"/>
        <xsl:for-each select="person">
            <xsl:value-of select="concat(id, ': ', name, '&#10;')"/>
        </xsl:for-each>
    </xsl:for-each>
</xsl:template>

https://xsltfiddle.liberty-development.net/jz1PuPb/1

通过支持高阶sort(例如 Saxon EE 或 PE),您还可以使用

<xsl:for-each select="sort(personNode, (), function($p) { count($p/person) })">

推荐阅读