XSLT Crie uma estrutura hierárquica a partir de uma estrutura plana usando certos critérios de nível

Eu quero criar uma estrutura XSD a partir de uma saída do Excel usando XSLT. Mas meu XSLT não gera a estrutura hierárquica corretamente. Ele possui alguns nós adicionais em um grupo de elementos, se esses nós com os mesmos parâmetros correspondentes forem definidos em um grupo posterior, que possui o mesmo nível na hierarquia.

A saída XML do Excel se parece com o seguinte:

 <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
 <nodes>
    <node typeTag="Test" nodeTag="GGG" minOccurs="0" segmentMaxOccurs="1" groupMaxOccurs="1000000">
        <metaInfo><ID>40</ID><Level>1</Level></metaInfo>
    </node>
    <node typeTag="Test" nodeTag="BBB" minOccurs="0" segmentMaxOccurs="1" groupMaxOccurs="1000000">
        <metaInfo><ID>60</ID><Level>2</Level></metaInfo>
    </node>
    <node typeTag="Test" nodeTag="XXX" minOccurs="0" segmentMaxOccurs="1000000" groupMaxOccurs="">
        <metaInfo><ID>80</ID><Level>2</Level></metaInfo>
    </node>
    <node typeTag="Test" nodeTag="AAA" minOccurs="0" segmentMaxOccurs="1" groupMaxOccurs="1000000">
        <metaInfo><ID>90</ID><Level>1</Level></metaInfo>
    </node>
    <node typeTag="Test" nodeTag="WWW" minOccurs="0" segmentMaxOccurs="1" groupMaxOccurs="1000000">
        <metaInfo><ID>110</ID><Level>1</Level></metaInfo>
    </node>
    <node typeTag="Test" nodeTag="OOO" minOccurs="0" segmentMaxOccurs="1" groupMaxOccurs="1000000">
        <metaInfo><ID>130</ID><Level>1</Level></metaInfo>
    </node>
    <node typeTag="Test" nodeTag="AAA" minOccurs="0" segmentMaxOccurs="1" groupMaxOccurs="1000000">
        <metaInfo><ID>140</ID><Level>2</Level></metaInfo>
    </node>
    <node typeTag="Test" nodeTag="WWW" minOccurs="0" segmentMaxOccurs="1" groupMaxOccurs="1000000">
        <metaInfo><ID>160</ID><Level>2</Level></metaInfo>
    </node>
 </nodes>

Cada nó deve ser um elemento, pelo qual @segmentMaxOccurs! = 0 irá gerar elemento folha e @groupMaxOccurs irá gerar elementos de grupo. O elemento "Level" define a hierarquia da estrutura (deve ser uma estrutura aninhada) e o elemento "ID" é um identificador exclusivo ordenado.

Com base nessa entrada, gostaria de obter a seguinte estrutura XSD. Para focar apenas no meu problema, removi todos os itens não relevantes, como "xs: sequence" ou "xs: complexType":

<?xml version="1.0" encoding="UTF-8"?>
<xs:element xmlns:xs="http://www.w3.org/2001/XMLSchema" name="Test">
    <xs:element name="GGG" minOccurs="0" maxOccurs="1000000" id="40">
        <xs:element name="GGG" minOccurs="0" maxOccurs="1" id="40"/>
        <xs:element name="BBB" minOccurs="0" maxOccurs="1000000" id="60">
            <xs:element name="BBB" minOccurs="0" maxOccurs="1" id="60"/>
            <xs:element name="XXX" minOccurs="0" maxOccurs="1000000" id="80"/>
        </xs:element>
    </xs:element>
    <xs:element name="AAA" minOccurs="0" maxOccurs="1000000" id="90">
        <xs:element name="AAA" minOccurs="0" maxOccurs="1" id="90"/>
    </xs:element>
    <xs:element name="WWW" minOccurs="0" maxOccurs="1000000" id="110">
        <xs:element name="WWW" minOccurs="0" maxOccurs="1" id="110"/>
    </xs:element>
    <xs:element name="OOO" minOccurs="0" maxOccurs="1000000" id="130">
        <xs:element name="OOO" minOccurs="0" maxOccurs="1" id="130"/>
        <xs:element name="AAA" minOccurs="0" maxOccurs="1000000" id="140">
            <xs:element name="AAA" minOccurs="0" maxOccurs="1" id="140"/>
        </xs:element>
        <xs:element name="WWW" minOccurs="0" maxOccurs="1000000" id="160">
            <xs:element name="WWW" minOccurs="0" maxOccurs="1" id="160"/>
        </xs:element>
    </xs:element>
</xs:element>

Mas eu apenas recebo a seguinte saída:

<?xml version="1.0" encoding="UTF-8"?>
<xs:element xmlns:xs="http://www.w3.org/2001/XMLSchema" name="Test">
    <xs:element name="GGG" minOccurs="0" maxOccurs="1000000" id="40">
        <xs:element name="GGG" minOccurs="0" maxOccurs="1" id="40"/>
        <xs:element name="BBB" minOccurs="0" maxOccurs="1000000" id="60">
            <xs:element name="BBB" minOccurs="0" maxOccurs="1" id="60"/>
            <xs:element name="XXX" minOccurs="0" maxOccurs="1000000" id="80"/>
        </xs:element>
        <xs:element name="AAA" minOccurs="0" maxOccurs="1000000" id="140">
            <xs:element name="AAA" minOccurs="0" maxOccurs="1" id="140"/>
        </xs:element>
        <xs:element name="WWW" minOccurs="0" maxOccurs="1000000" id="160">
            <xs:element name="WWW" minOccurs="0" maxOccurs="1" id="160"/>
        </xs:element>
    </xs:element>
    <xs:element name="AAA" minOccurs="0" maxOccurs="1000000" id="90">
        <xs:element name="AAA" minOccurs="0" maxOccurs="1" id="90"/>
    </xs:element>
    <xs:element name="WWW" minOccurs="0" maxOccurs="1000000" id="110">
        <xs:element name="WWW" minOccurs="0" maxOccurs="1" id="110"/>
    </xs:element>
    <xs:element name="OOO" minOccurs="0" maxOccurs="1000000" id="130">
        <xs:element name="OOO" minOccurs="0" maxOccurs="1" id="130"/>
        <xs:element name="AAA" minOccurs="0" maxOccurs="1000000" id="140">
            <xs:element name="AAA" minOccurs="0" maxOccurs="1" id="140"/>
        </xs:element>
        <xs:element name="WWW" minOccurs="0" maxOccurs="1000000" id="160">
            <xs:element name="WWW" minOccurs="0" maxOccurs="1" id="160"/>
        </xs:element>
    </xs:element>
</xs:element>

O grupo "GGG" possui os dois grupos adicionais AAA (id = 140) e WWW (id = 160), que devem estar logo abaixo do grupo OOO. Você tem alguma idéia de como apenas os nós corretos do GGG serão processados até o grupo AAA (id = 90), que está no mesmo nível do grupo de elementos "GGG". Não tenho ideia de como serão consumidos esses nós que pertencem ao grupo de elementos "GGG".

Esta é a parte do XSLT, que é relevante para gerar a estrutura hierárquica:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:nestor="http://sap.com/ia" xmlns:ns1="http://www.sap.com/ia" xmlns:functx="http://sap.com/xslt/functions">
    <xsl:output method="xml" indent="yes"/>
    <xsl:param name="pRootNode" select="'Test'"/>
    <xsl:template match="nodes">
        <xsl:variable name="vRootNode" select="$pRootNode"/>
        <xsl:element name="xs:element">
            <xsl:attribute name="name" select="$vRootNode"/>
            <xsl:variable name="vLevel" select="0"/>
            <xsl:variable name="vNextLevel" select="1"/>
            <xsl:variable name="vGroupCounter" select="node[@typeTag = $vRootNode and @groupMaxOccurs != '']"/>
            <xsl:apply-templates select="node[@typeTag = $vRootNode and ((@groupMaxOccurs != '' and ./metaInfo/Level = $vNextLevel) or (@groupMaxOccurs = '' and ./metaInfo/Level = $vLevel))]" mode="MessageStructure">
                <xsl:with-param name="pRootNode" select="$vRootNode"/>
                <xsl:with-param name="pLevel" select="$vLevel"/>
                <xsl:with-param name="pGroupCounter" select="$vGroupCounter"/>
            </xsl:apply-templates>
        </xsl:element>
    </xsl:template>
    <xsl:template match="node[@groupMaxOccurs = '']" mode="MessageStructure">
        <xsl:param name="pRootNode"/>
        <xsl:param name="pLevel"/>
        <xsl:param name="pGroupCounter"/>
        <xsl:variable name="vActGroupCounter" select="count(following-sibling::node[@typeTag = $pRootNode and @groupMaxOccurs != ''])"/>
        <xsl:if test="./metaInfo/Level = $pLevel and ($vActGroupCounter = $pGroupCounter or $pLevel = 0)">
            <xsl:element name="xs:element">
                <xsl:attribute name="name" select="@nodeTag"/>
                <xsl:attribute name="minOccurs" select="@minOccurs"/>
                <xsl:attribute name="maxOccurs" select="@segmentMaxOccurs"/>
                <xsl:attribute name="id" select="./metaInfo/ID"/>
            </xsl:element>
        </xsl:if>
    </xsl:template>
    <xsl:template match="node[@groupMaxOccurs != '']" mode="MessageStructure">
        <xsl:param name="pRootNode"/>
        <xsl:param name="pLevel"/>
        <xsl:param name="pGroupCounter"/>
        <xsl:variable name="vNextLevel" select="$pLevel + 1"/>
        <xsl:variable name="vActGroupCounter" select="count(following-sibling::node[@typeTag = $pRootNode and @groupMaxOccurs != ''])"/>
        <xsl:variable name="vNextGroupLevel" select="following-sibling::node[@typeTag = $pRootNode and @groupMaxOccurs != ''][1]/metaInfo/Level"/>
        <xsl:element name="xs:element">
            <xsl:attribute name="name" select="@nodeTag"/>
            <xsl:attribute name="minOccurs" select="@minOccurs"/>
            <xsl:attribute name="maxOccurs" select="@groupMaxOccurs"/>
            <xsl:attribute name="id" select="./metaInfo/ID"/>
            <xsl:element name="xs:element">
                <xsl:attribute name="name" select="@nodeTag"/>
                <xsl:attribute name="minOccurs" select="@minOccurs"/>
                <xsl:attribute name="maxOccurs" select="@segmentMaxOccurs"/>
                <xsl:attribute name="id" select="./metaInfo/ID"/>
            </xsl:element>
            <xsl:apply-templates select="following-sibling::node[@typeTag = $pRootNode and ((@groupMaxOccurs != '' and ./metaInfo/Level = $vNextLevel + 1 and ./metaInfo/Level = $vNextGroupLevel) or (@groupMaxOccurs = '' and ./metaInfo/Level = $vNextLevel))]" mode="MessageStructure">
                <xsl:with-param name="pRootNode" select="$pRootNode"/>
                <xsl:with-param name="pLevel" select="$vNextLevel"/>
                <xsl:with-param name="pGroupCounter" select="$vActGroupCounter"/>
            </xsl:apply-templates>
        </xsl:element>
    </xsl:template>
</xsl:stylesheet>

Qualquer apoio é realmente apreciado. Muito obrigado antecipadamente.

questionAnswers(2)

yourAnswerToTheQuestion