2010-08-23 7 views
1

Je produis du texte avec XSLT. J'ai besoin de compter le nombre de lignes de chaque section et l'écrire dans mon fichier de sortie. Comment cela pourrait-il être fait?Comment compter les lignes de sortie avec xslt?

Ma sortie est comme ceci:

 
HDR+aaa:bbb' 
AAA+789String1:String2' 
BBB+123+String' 
CCC+321:1212' 
DDD+112211' 
DDD+121122' 
XXX+number_of_records+789' 
AAA+1234567890+String1:String2' 
BBB+123+String' 
CCC+321:1212' 
DDD+1212:2121' 
BBB+123+String' 
BBB+122+String' 
CCC+String' 
XXX+number_of_records+1234567890' 

Les number_of_records doivent contenir nombre de lignes de AAA à XXX, y compris les deux lignes. Dans la première section, le nombre de lignes devrait être de 6 et dans le deuxième message, il devrait être de 8. La première et la dernière ligne de chaque section partageront le même numéro d'identification unique.

Le nombre de lignes ne peut pas être compté à partir de la source car il y a tellement de traitement dans XSLT.

+1

Sans l'entrée ou un échantillon de celui-ci, personne ne pourra vous donner beaucoup d'aide ici. Utilisez-vous XSLT 1 ou 2; Quel processeur utilisez-vous? –

+0

Publiez également votre XSLT, car cela sera nécessaire afin de discerner ce qui est nécessaire –

Répondre

1

Juste pour le plaisir, jusqu'à ce que vous postez votre échantillon d'entrée et le renforcement des stylesheet que la production de texte, cette feuille de style:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output method="text"/> 
    <xsl:template match="result" name="result"> 
     <xsl:param name="pString" select="."/> 
     <xsl:variable name="vAfter" select="substring-after($pString, 'AAA+')"/> 
     <xsl:choose> 
      <xsl:when test="$vAfter!=''"> 
       <xsl:variable name="vId" 
         select="substring-before($vAfter, '+')"/> 
       <xsl:variable name="vEnd" 
        select='concat("XXX+number_of_records+",$vId,"&apos;&#xA;")'/> 
       <xsl:variable name="vInto" 
         select="substring-before($vAfter,$vEnd)"/> 
       <xsl:value-of 
         select='concat(substring-before($pString,"AAA+"), 
          "AAA+", 
          $vInto, 
          "XXX+", 
          string-length(translate($vInto, 
                translate($vInto, 
                   "&#xA;", 
                   ""), 
                "")) + 1, 
          "+",$vId,"&apos;&#xA;")'/> 
       <xsl:call-template name="result"> 
        <xsl:with-param name="pString" 
         select="substring-after($vAfter,$vEnd)"/> 
       </xsl:call-template> 
      </xsl:when> 
      <xsl:otherwise> 
       <xsl:value-of select="$pString"/> 
      </xsl:otherwise> 
     </xsl:choose> 
    </xsl:template> 
</xsl:stylesheet> 

Avec cette entrée:

<result> 
HDR+aaa:bbb' 
AAA+789String1:String2' 
BBB+123+String' 
CCC+321:1212' 
DDD+112211' 
DDD+121122' 
XXX+number_of_records+789' 
AAA+1234567890+String1:String2' 
BBB+123+String' 
CCC+321:1212' 
DDD+1212:2121' 
BBB+123+String' 
BBB+122+String' 
CCC+String' 
XXX+number_of_records+1234567890' 
</result> 

Sortie:

HDR+aaa:bbb' 
AAA+789String1:String2' 
BBB+123+String' 
CCC+321:1212' 
DDD+112211' 
DDD+121122' 
XXX+6+789' 
AAA+1234567890+String1:String2' 
BBB+123+String' 
CCC+321:1212' 
DDD+1212:2121' 
BBB+123+String' 
BBB+122+String' 
CCC+String' 
XXX+8+1234567890' 
2

Une manière conceptuellement simple de faire cela serait d'utiliser un processus de deuxième étape. Prenez la sortie de votre transformation initiale (ce que vous avez posté) et exécutez-la à travers un modèle (ou une feuille de style comme @ Alejandro) qui l'analyse en lignes, et regroupe les lignes commençant par AAA ... et se terminant par XXX. Voir Up-conversion using XSLT 2.0 pour un tutoriel très clair et pratique sur ce faire, en utilisant tokenize(), xsl:analyze-string, et xsl:for-each-group. Puis comptez les lignes dans chaque groupe, et re-sortie chaque ligne, branchez le nombre de lignes dans l'enregistrement XXX.

Mais c'est inefficace, et un peu sujet aux erreurs, puisque vous seriez en train d'analyser la sortie initiale. Pourquoi analyser une sérialisation d'informations que la feuille de style avait déjà en interne? Vous pouvez éviter l'inefficacité en changeant votre sortie initiale au format XML, quelque chose comme

<hdr> 
    <section id="789"> 
    <!-- It sounds like AAA's ID actually applies to the section? --> 
    <AAA String1="..." String2="..."/> 
    <BBB .../> 
    <!-- no need to include XXX at this stage AFAICT --> 
    </section> 
    <section id="1234567890"> 
    ... 
    </section> 
</hdr> 

Ensuite, le modèle de deuxième étape (ou une feuille de style séparée) pourrait prendre cette XML en entrée et sérialisation très facilement comme vous l'avez fait ci-dessus , en comptant les lignes comme ça va. Dans XSLT 1.0, vous devez utiliser une feuille de style séparée pour traiter le fichier XML de sortie, ou utiliser le extension function node-set(). (Mais même avec un processeur de feuille de style séparé, vous pouvez toujours éviter le coût de ré-analyse du XML intermédiaire, si vous pouvez assembler les deux processeurs de feuille de style en utilisant SAX.) Dans XSLT 2.0, vous pouvez traiter la sortie XML d'un modèle avec un autre modèle, sans restriction.

0

Ma solution: J'ai créé une fonction d'extension qui incrémente le nombre de registres de un chaque fois que je l'appelle. J'utilise xsl: comment supprimer la sortie jusqu'à ce que j'ai vraiment besoin de sortir le nombre. Je réinitialise le number_of_records après chaque XXX + -line.

Faire cela en deux étapes aurait causé trop de tracas.