Search code examples
xmlxsltxslt-2.0xslt-3.0

XSLT: Distinct names of child nodes


<mensagens>
        <mensagem maquina="M02" timestamp="2020-05-22T15:28:50+0000">
            <inicioAtividade>
                <contexto>
                    <tipo>OP</tipo>
                    <descricao>12345</descricao>
                </contexto>
            </inicioAtividade>
        </mensagem>

        <mensagem maquina="M03" timestamp="2020-05-22T15:29:46-0400">
            <fimAtividade>
                <contexto>
                    <tipo>OP</tipo>
                    <descricao>12345</descricao>
                </contexto>
            </fimAtividade>
        </mensagem>

        <mensagem maquina="M03" timestamp="2020-05-22T15:29:46-0400">
            <paragemForcada>
                <causa id="fdbs"/>
            </paragemForcada>
        </mensagem>

        <mensagem maquina="M02" timestamp="2020-05-22T18:28:46-0400">
            <consumo>
                <materiaPrima id="PC3025"/>
                <quantidade>200</quantidade>
                <origem>
                    <maquina id="M01"/>
                </origem>
            </consumo>
        </mensagem>

        <mensagem maquina="M01" timestamp="2020-05-23T15:28:46-0400">
            <producao>
                <produto id="PC3025"/>
                <quantidade>10</quantidade>
            </producao>
        </mensagem>

        <mensagem maquina="M03" timestamp="2020-06-22T15:28:46-0400">
            <entregaProducao>
                <quantidade>10</quantidade>
                <produto id="RC1.3"/>
                <deposito id="DEP1"/>
            </entregaProducao>
        </mensagem>

        <mensagem maquina="M01" timestamp="2020-05-31T15:28:46-0400">
            <estorno>
                <quantidade>10</quantidade>
                <materiaPrima id="RC1.2"/>
                <deposito id="DEP1"/>
            </estorno>
        </mensagem>
    </mensagens>

I'm trying to get all the names of child nodes of 'mensagem'.

Output would be: inicioAtividade, fimAtividade, paragemForcada, etc.

I already know how to get the child of mensagem name but I'm having trouble getting every distinct name

My template starts at mensagens

How could I get something like this?


Solution

  • Simply use this XSLT expression:

    <xsl:value-of select="distinct-values(mensagem/*/name())" separator=", " />
    

    Its output is

    inicioAtividade, fimAtividade, paragemForcada, consumo, producao, entregaProducao, estorno

    To count each occurrence of a distinct name, you could use this template:

    <xsl:template match="/mensagens">
      <xsl:for-each-group select="mensagem/*" group-by="name()">
        <xsl:value-of select="concat(count(current-group()),' - ',current-grouping-key())" />
        <xsl:text>&#xa;</xsl:text>
      </xsl:for-each-group>
    </xsl:template>
    

    Its output is

    1 - inicioAtividade
    1 - fimAtividade
    1 - paragemForcada
    1 - consumo
    1 - producao
    1 - entregaProducao
    1 - estorno