2010-06-22 5 views
3

je le code XML suivant (simplification):Réduire répéter l'expression dans XSLT 1.0

<?xml version="1.0" encoding="utf-8"?> 
<TestCases> 
    <TestCase> 
    <Name>Test1</Name> 
    <Result>Failed</Result> 
    <Properties> 
     <Type>Type1</Type> 
    </Properties> 
    </TestCase> 
    <TestCase> 
    <Name>Test1</Name> 
    <Result>Failed</Result> 
    <Properties> 
     <Type>Type2</Type> 
    </Properties> 
    </TestCase> 
    <TestCase> 
    <Name>Test1</Name> 
    <Result>Passed</Result> 
    <Properties> 
     <Type>Type1</Type> 
    </Properties> 
    </TestCase> 
</TestCases> 

Je suis intéressé à créer une table qui compte le nombre de cas de test passé/échec, selon leur type, comme si :

Passé (Type1): 1 Échec (Type1): 1 défini (Autres types): 0 échouées (Autres types): 1

Pour ce faire, je suis en train d'écrire la requête suivante:Comme vous pouvez le voir, il y a beaucoup de répétitions de code qui se passe et serait génial si je pouvais en sauver une partie. Je comprends que dans XSL 2.0 je pourrais utiliser des fonctions utilisateur pour cela, mais que dois-je faire dans XSL 1.0? Voyez-vous des options que vous pouvez voir pour optimiser les expressions répétitives?

P.S Notez qu'il s'agit d'une simplification du réel et bien que l'expression ne semble pas longue ici, dans le vrai code c'est assez long donc le besoin est bien réel.

Merci!

+0

Bonne question (1). Voir ma réponse pour une solution qui utilise '' pour définir les variables. –

Répondre

3

Essayez:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 

    <xsl:key name="byType" match="Properties/Type" use="."/> 

    <xsl:template match="text()" /> 

    <xsl:template match="Type[count(.|key('byType',.)[1])=1]"> 
     <xsl:value-of select="concat(' Passed (',.,'): ', 
             count(key('byType',.)[../../Result='Passed']), 
             ' Failed (',.,'): ', 
             count(key('byType',.)[../../Result='Failed']))" /> 
    </xsl:template> 

</xsl:stylesheet> 

Et vous obtenez:

Passed (Type1): 1 Failed (Type1): 1 Passed (Type2): 0 Failed (Type2): 1 

Modifier: moins bavard.

+0

Wow, vous pensez que vous connaissez * un peu * XSLT et que vous voyez des choses que vous n'avez jamais vues auparavant. Je vais essayer et revenir à vous. Merci. – VitalyB

+0

Intresting. Je ne pensais pas pouvoir faire de telles choses avec des expressions. S'il s'agit bien d'une chaîne de caractères et qu'elle est ouverte aux manipulations, puis-je aussi déclarer une variable en utilisant et l'utiliser dans l'expression? – VitalyB

+0

@VitalyB: Oui. Vous pouvez utiliser des variables et des paramètres dans les expressions xpath, mais vous ne pouvez pas les utiliser dans les modèles. Exemple: '' –

1

En plus de l'excellente solution bu @Alejandro en utilisant la méthode Muenchian pour le regroupement, voici un qui illustre l'utilisation des variables:

Cette transformation:

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output method="text"/> 

<xsl:variable name="vPassed" 
     select="/*/*[Result = 'Passed']"/> 

<xsl:variable name="vFailed" 
     select="/*/*[Result = 'Failed']"/> 

<xsl:template match="/"> 
    <xsl:value-of select= 
    "concat('Passed (Type1): ', 
      count($vPassed[Properties/Type='Type1']), 
      ' Failed (Type1): ', 
      count($vFailed[Properties/Type='Type1']), 
      ' Passed (Other types): ', 
      count($vPassed[not(Properties/Type='Type1')]), 
      ' Failed (Other types): ', 
      count($vFailed[not(Properties/Type='Type1')]) 
     ) 
    "/> 
</xsl:template> 
</xsl:stylesheet> 

quand appliqué sur le document XML fourni:

<TestCases> 
    <TestCase> 
    <Name>Test1</Name> 
    <Result>Failed</Result> 
    <Properties> 
     <Type>Type1</Type> 
    </Properties> 
    </TestCase> 
    <TestCase> 
    <Name>Test1</Name> 
    <Result>Failed</Result> 
    <Properties> 
     <Type>Type2</Type> 
    </Properties> 
    </TestCase> 
    <TestCase> 
    <Name>Test1</Name> 
    <Result>Passed</Result> 
    <Properties> 
     <Type>Type1</Type> 
    </Properties> 
    </TestCase> 
</TestCases> 

produit le résultat souhaité, correct:

Passed (Type1): 1 Failed (Type1): 1 Passed (Other types): 0 Failed (Other types): 1 
+0

Intéressant! 2 questions: 1) Pourquoi n'avez-vous défini que des expressions Passées/Échec? Que diriez-vous de définir aussi variable pour les types? E.g: '' Ensuite, vous pouvez écrire: 'count (vPassed $ [$ vType1]) ' 2) Je suis confus au sujet de votre syntaxe: ' ' Pourquoi avez-vous ajouté/*/* devant? – VitalyB

+0

@VitalyB: 1) Ce que vous suggérez: 'count ($ vPassed [$ vType1])' sélectionne toujours tous les nœuds dans '$ vPassed' si' $ vType1' est non-vide. Vous devez apprendre XPath. C'est la raison pour laquelle je n'ai pas choisi cette route. Pour votre question 2) - encore apprendre XPath - en particulier lire sur le nœud de contexte, les expressions absolues et relatives. –

+0

Merci! Je vais. – VitalyB

Questions connexes