2017-08-23 3 views
0

Considérez mon fichier XML:compteur de remise à zéro dans v2.0 xslt

<Data> 
    <VetaP dfg="2" ppp="oe"/> 
    <VetaD ods="3" ds="oda"/> 
    <VetaR date="080817"/> 
    <VetaR date=""/> 
    <VetaR date=""/> 
    <VetaR date=""/> 
    <VetaR date="080817"/> 
    <VetaR date=""/> 
    <VetaR date=""/> 
    <VetaR date="080817"/> 
</Data> 

Je dois ajouter un attribut suivants dans <VetaR>, cet attribut est un compteur pour chaque vetar créé. Mais, j'ai besoin de réinitialiser le compteur pour toutes les 5 occurrences de <VetaR>. J'ai besoin d'ajouter aussi un attribut cnt, dans lequel, c'est aussi un compteur, mais cette fois il ne sera incrémenté que pour toutes les 5 occurrences de <VetaR>. J'ai besoin d'enlever aussi les attributs vides.

Voici mon code XSLT:

Courant de sortie:

<Data> 
    <VetaP dfg="2" ppp="oe"/> 
    <VetaD ods="3" ds="oda"/> 
    <VetaR seq="3" cnt="1" date="080817"/> 
    <VetaR seq="4" cnt="1"/> 
    <VetaR seq="5" cnt="1"/> 
    <VetaR seq="1" cnt="2"/> 
    <VetaR seq="2" cnt="2" date="080817"/> 
    <VetaR seq="3" cnt="2"/> 
    <VetaR seq="4" cnt="2"/> 
    <VetaR seq="5" cnt="2" date="080817"/></Data> 

sortie souhaitée:

<Data> 
    <VetaP dfg="2" ppp="oe"/> 
    <VetaD ods="3" ds="oda"/> 
    <VetaR seq="1" cnt="1" date="080817"/> 
    <VetaR seq="2" cnt="1"/> 
    <VetaR seq="3" cnt="1"/> 
    <VetaR seq="4" cnt="1"/> 
    <VetaR seq="5" cnt="1" date="080817"/> 
    <VetaR seq="1" cnt="2"/> 
    <VetaR seq="2" cnt="2"/> 
    <VetaR seq="3" cnt="2" date="080817"/></Data> 
+0

En pensant à cela en termes de remise à zéro des compteurs, vous pensez à la façon dont vous résoudre le problème si vous utilisez un langage de programmation procédural plutôt que un fonctionnel. Essayez de ne pas «dire à l'ordinateur ce qu'il faut faire», mais plutôt de décrire comment la sortie se rapporte à l'entrée. –

Répondre

2

Je l'aborder comme groupement de position:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:xs="http://www.w3.org/2001/XMLSchema" 
    exclude-result-prefixes="xs" 
    version="2.0"> 

    <xsl:output indent="yes"/> 

    <xsl:template match="@* | node()"> 
     <xsl:copy> 
      <xsl:apply-templates select="@* | node()"/> 
     </xsl:copy> 
    </xsl:template> 

    <xsl:template match="Data"> 
     <xsl:copy> 
      <xsl:for-each-group select="*" group-adjacent="(position() - 1) idiv 5"> 
       <xsl:apply-templates select="current-group()"> 
        <xsl:with-param name="group-pos" select="position()"/> 
       </xsl:apply-templates> 
      </xsl:for-each-group> 
     </xsl:copy> 
    </xsl:template> 

    <xsl:template match="VetaR"> 
     <xsl:param name="group-pos"/> 
     <VetaR seq="{position()}" cnt="{$group-pos}"> 
      <xsl:apply-templates select="@*"/> 
     </VetaR> 
    </xsl:template> 

    <xsl:template match="VetaR/@*[not(normalize-space())]"/> 
</xsl:stylesheet> 
+0

Merci, et si j'avais un autre élément avant le VetaR? Je ne peux pas obtenir la sortie correcte, la position a commencé à 2. Fichier d'entrée mis à jour. –

+0

Eh bien, si les autres éléments sont connus pour être avant tous les éléments 'VetaR' alors vous pouvez facilement corriger le code en les traitant d'abord et séparément avec, par exemple. ' ... '. Si l'entrée est plus variable alors je suppose que vous devrez nous montrer plus de détails de l'entrée et de la sortie désirée. –

2

Pourquoi ne pas simplement:

<xsl:template match="VetaR"> 
    <VetaR seq="{(position() - 1) mod 5 + 1}" cnt="{(position() - 1) idiv 5 + 1}"> 
     <xsl:if test="string(@date)"> 
      <xsl:copy-of select="@date"/> 
     </xsl:if> 
    </VetaR> 
</xsl:template>