2010-02-12 5 views
3

Je souhaite utiliser XSLT pour transformer un ensemble de documents en une structure. J'ai la transformation qui fonctionne correctement pour concaténer les documents. Je ne sais pas, cependant, si les documents ont des entrées en double, que je devrai supprimer.Noeuds xml uniques basés sur l'attribut

J'ai besoin de savoir comment supprimer ces doublons (s'ils existent) par un attribut id. Tous les doublons auront le même identifiant. Je sais que cela aura quelque chose à voir avec les touches et les fonctions generate-id.

<root> 
    <item id="1001">A</item> 
    <item id="1003">C</item> 
    <item id="1004">D</item> 
    <item id="1002">B</item> 
    <item id="1001">A</item> 
    <item id="1003">C</item> 
    <item id="1004">D</item> 
    <item id="1005">E</item> 
</root> 

je besoin d'une transformation XSLT 1.0 pour ce qui précède, selon les critères suivants ...

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

Aussi, quelqu'un pourrait-il expliquer comment cela fonctionne pour moi aussi? Bit d'un noob ...

Merci à l'avance ...

Répondre

3

Communément solutions sont présentées avec l'utilisation de generate-id() mais personnellement je préfère une variation légèrement différente qui n'utilise pas générer-id: -

<xsl:key name="items" match="item" use="@id" /> 

<xsl:template match="root"> 
    <root> 
     <xsl:copy-of select="item[count(key('items',@id)[1]|.)=1]" /> 
    </root> 
</xsl:template> 

Vous devez d'abord créer une clé qui contient tous les éléments de l'élément en utilisant l'attribut id comme clé de référence. key génère un index efficace qui peut être utilisé pour rechercher des éléments.

La technique repose sur le fait que lorsque vous créez un ensemble de nœuds à l'aide de l'opérateur |, vous obtenez un ensemble unique de nœuds. En d'autres termes, si le même nœud se trouve des deux côtés de l'opérateur |, il n'apparaît qu'une seule fois dans l'ensemble résultant.

L'expression: -

key('items',@id) 

sera de retour l'ensemble des noeuds d'éléments qui ont un ID spécifique. Alors: -

key('items',@id)[1] 

ne retourneront que dans l'un des noeuds qui ont été trouvés ont qu'une pièce d'identité spécifique et est reproductible (qui est d'utiliser cette expression revient à plusieurs reprises toujours le même nœud).

D'où l'expression: -

count(key('items',@id)[1]|.)=1 

est ne peut être vrai pour un noeud item avec un identifiant spécifique.

Le copy-of effectue donc une copie en profondeur d'un seul nœud d'élément ayant un ID distinct.

+0

@Anthony: My 0.02 $ - alors que l'approche 'count()' prend moins de place, elle est également plus difficile à comprendre. Preuve: La longue explication. :) L'approche 'generate-id()' est moins opaque, c'est pourquoi je recommande toujours ce dernier. Il y a * cas * où la méthode 'count() est la seule option, mais ils sont rares et éloignés. (edit: still, +1) – Tomalak

3

Voici le generate-id() façon @AnthonyWJones mentionné. Je trouve celui-ci beaucoup plus facile sur l'esprit humain. Cela ne fait aucune différence dans le résultat, choisissez ce que vous préférez.

<xsl:stylesheet 
    version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
> 
    <xsl:key name="kItemById" match="item" use="@id" /> 

    <xsl:template match="root"> 
    <copy> 
     <xsl:copy-of select=" 
     item[generate-id() = generate-id(key('kItemById', @id)[1])] 
     " /> 
    </copy> 
    </xsl:template> 
</xsl:stylesheet> 

En bref:

item[generate-id() = generate-id(key('kItemById', @id)[1])] 

signifie: "Tous les <item> s, dont ID unique est égal à l'ID unique de premier élément avec la même valeur @id".

+0

+1 Je suis d'accord que l'utilisation de generate-id est plus facile à comprendre. – AnthonyWJones

Questions connexes