Question

J'ai du XML, par exemple, il se présente comme suit:

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

Je veux le transformer avec XSLT, mais je veux supprimer le deuxième élément f2 de la sortie - comment puis-je vérifier dans mon modèle pour voir si l'élément f2 existe déjà dans la sortie lorsque le deuxième élément f2 du 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 pense que je dois vérifier quelque chose autour de l'élément xsl: dans le modèle, mais je ne sais pas comment interroger le document de sortie pour voir si l'élément est déjà présent.

Modifier: vous avez oublié les balises de pré, le code devrait être visible maintenant!

Était-ce utile?

La solution

Cela dépend de la largeur de votre système.

i.e. Ne vous préoccupez que des éléments qui sont des enfants du même parent, ou de tous les éléments du même niveau ('cousins' si vous préférez) ou des éléments n'importe où dans le document ...

Dans le premier cas, vous pouvez vérifier l'axe des frères précédents pour voir s'il existe d'autres éléments portant le même nom.

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

Autres conseils

Pour vérifier uniquement (et vous avertir d’un doublon), vous pouvez trouver un exemple ici

Quelque chose dans le sens 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 nœuds au sein de l'élément 'root'.

Pour supprimer les doublons, vous avez un autre exemple. ici

Cela ressemblerait à:

<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 souhaitez rendre unique. Ce peut être concat (x, '-', @ y, '-', z) ou ce que vous voulez.

Maintenant, je ne suis pas sûr que ces deux exemples puissent facilement être adaptés à votre cas, mais je voulais simplement souligner ces deux sources, au cas où cela vous aiderait.

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 garder trace des nœuds que vous avez émis dans une variable). Fondamentalement, ce n'est pas comme ça que XSLT fonctionne. 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. Oh bien.

Dans votre cas, un moyen d'y parvenir serait de construire une variable contenant la liste de tous les éléments source pouvant être transformés en élément de sortie que vous ne souhaitez émettre qu'une seule fois. Puis vérifiez chaque noeud que vous êtes en train de transformer par rapport à cette liste. Si ce n'est pas dans la liste, émettez-le. S'il s'agit du premier élément de la liste, émettez-le. Sinon, ne le faites pas.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top