Как отсортировать результаты внутри преобразования XSLT? - PullRequest
0 голосов
/ 28 октября 2019

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

Можно ли отсортировать результаты в преобразовании xslt перед записью их в выходной поток?

Моя цель: 1) преобразовать следующий xml в csv, 2) отсортировать людей по количеству <person> вхождений в <personNode>.

Пример: далее в последнем узле человека содержатся только1 человек. Поэтому я хочу отсортировать этого человека поверх всех результатов в конечном выводе.

Затем должны быть напечатаны все люди, которые были в узлах с двумя людьми. Затем 3 ..., затем N.

source.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>? Может быть, мне пришлось бы собирать строки csv внутри переменной map или list, а затем снова в конце цикла с выводом на печать?

Ответы [ 2 ]

1 голос
/ 28 октября 2019

Используйте 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) })">
1 голос
/ 28 октября 2019

Как насчет этого?

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