2008-10-01 19 views
4

J'ai quelques XML, par exemple, des fins, il ressemble à ceci:Vérification d'un élément en double dans la sortie

<root> 
    <field1>test</field1> 
    <f2>t2</f2> 
    <f2>t3</f2> 
</root> 

Je veux la transformer avec XSLT, mais je veux supprimer le deuxième élément f2 dans la sortie - comment vérifier dans mon modèle pour voir si l'élément f2 existe déjà dans la sortie lorsque le second élément f2 de la source est traité? Mon XSLT ressemble à ceci à l'heure actuelle:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output method="xml" indent="no" omit-xml-declaration="yes" standalone="no" /> 
    <xsl:template match="/"> 
    <xsl:for-each select="./root"> 
     <output> 
     <xsl:apply-templates />   
     </output> 
    </xsl:for-each> 
    </xsl:template> 
    <xsl:template match="*" > 
     <xsl:element name="{name(.)}"> 
     <xsl:value-of select="." /> 
     </xsl:element> 
    </xsl:template> 
</xsl:stylesheet> 

je dois faire une sorte de contrôle autour de l'élément xsl: dans le modèle que je pense, mais je ne suis pas sûr de savoir comment interroger le document de sortie pour voir si l'élément est déjà présent.

Modifier: Les balises pré oubliées, le code devrait être visible maintenant!

Répondre

7

Cela dépend de la largeur du système que vous voulez.

-à-dire Êtes-vous ne concerne que les éléments qui sont des enfants du même parent, ou tous les éléments au même niveau (« cousins ​​» si vous le souhaitez) ou des éléments partout dans le document ...

Dans le premier Dans la situation, vous pouvez vérifier l'axe précédent-frère pour voir si d'autres éléments existent avec le même nom.

<xsl:if test="count(preceding-sibling::node()[name()=name(current())])=0"> 
    ... do stuff in here. 
</xsl:if> 
+0

Vous pourriez également simplement faire un modèle avec ce prédicat, je pense. –

+0

C'est parfait.Oui, j'ai juste besoin de supprimer les doublons dans le même parent, je veux autoriser explicitement les mêmes éléments dans les autres parents - cela fonctionne très bien et est beaucoup plus simple que l'itinéraire que je descendais en utilisant les clés et la méthode Muenchen! –

1

Pour seulement vérifier (et vous avertir d'un double), vous pouvez trouver un example here

Quelque chose le long des lignes de:

<xsl:for-each-group select="collection(...)//@id" group-by="."> 
    <xsl:if test="count(current-group()) ne 1"> 
    <xsl:message>Id value <xsl:value-of select="current-grouping-key()"/> is 
     duplicated in files 
     <xsl:value-of select="current-group()/document-uri(/)" separator=" and 
    "/></xsl:message> 
    </xsl:if> 
</xsl:for-each-group> 

à modifier pour sélectionner tous les noeuds ' root 'élément.

à éliminer les lignes en double, vous avez une autre example here

Ce ressembleraient:

<xsl:stylesheet> 
    <xsl:key name="xyz" match="record[x/y/z]" use="x/y/z" /> 
    <xsl:variable name="noxyzdups" select="/path/to/record[generate-id(.) = generate-id(key('xyz', x/y/z))]" /> 
... 
    <xsl:template ... > 
    <xsl:copy-of "exslt:node-set($noxyzdups)" /> 
    </xsl:template> 
</xsl:stylesheet> 

x/y/z est l'expression XPath que vous voulez fait unique. Il peut être concat (x, '-', @ y, '-', z) ou ce que vous voulez. Maintenant, je ne suis pas sûr que ces deux exemples peuvent facilement être adaptés à votre cas, mais je voulais juste souligner ces deux sources, dans le cas où cela aide.

+0

Oui, c'était la route que je descendais, et je pense que j'aurais pu le faire fonctionner, mais le contrôle plus simple ci-dessus est mieux adapté à mes besoins. Merci quand même. –

1

Il n'est pas possible d'interroger la sortie de votre transformation. Il n'est également pas possible de suivre l'état actuel de votre transformation (c'est-à-dire de suivre les nœuds que vous avez émis dans une variable). Fondamentalement, ce n'est pas comme ça que fonctionne XSLT. L'un des coûts d'un environnement de programmation sans effets secondaires est que vous ne pouvez pas faire des choses qui ont des effets secondaires. Tant pis. Dans votre cas, une façon d'y parvenir consisterait à créer une variable contenant une liste de tous les éléments source qui pourraient être transformés en un élément de sortie que vous ne souhaitez émettre qu'une seule fois. Ensuite, vérifiez chaque nœud que vous transformez dans cette liste. Si ce n'est pas dans la liste, l'émettre. Si c'est le premier élément de la liste, l'émettre. Sinon, ne le faites pas.