8
votes

Comment puis-je empêcher les doublons, dans XSL?

Comment puis-je éviter les entrées en double dans une liste, puis idéalement, trier cette liste? Ce que je fais, c'est que lorsque des informations à un niveau sont manquantes, prenant les informations d'un niveau inférieur à celui-ci, de construire la liste manquante, au niveau ci-dessus. Actuellement, j'ai XML similaire à celui-ci:

<c03 id="ref6488" level="file">
    <did>
        <container label="Box" type="Box">154, 156</container>
        <unittitle>Clinic Building</unittitle>
        <unitdate era="ce" calendar="gregorian">1947</unitdate>
    </did>
    <c04 id="ref34582" level="file">
        <did>
            <container label="Box" type="Box">156</container>
            <container label="Folder" type="Folder">3</container>
        </did>
    </c04>
    <c04 id="ref6540" level="file">
        <did>
            <container label="Box" type="Box">156</container>
            <unittitle>Contact prints</unittitle>
        </did>
    </c04>
    <c04 id="ref6606" level="file">
        <did>
            <container label="Box" type="Box">154</container>
            <unittitle>Negatives</unittitle>
        </did>
    </c04>
</c03>


1 commentaires

Bonne question (+1). Consultez ma réponse pour une solution XSLT 1.0 qui est plus courte que la solution XSLT 2.0 actuellement sélectionnée. :)


6 Réponses :


1
votes

Essayez d'utiliser un groupe clé dans XSLT, voici un article sur la méthode Muenchian qui devrait aider à éliminer les doublons. http://www.jenitennison.com/xslt/grouping/muenchian.htmlLeight >


1 commentaires

L'article de Jeni explique très bien la méthode méchogique pour le mal de la pensée (comme moi)!



2
votes

Essayez le code suivant:

<?xml version="1.0" encoding="UTF-8"?>
<c03 id="ref6488" level="file">
  <did>
      <container label="Box" type="Box">154, 156</container>
      <unittitle>Clinic Building</unittitle>
      <unitdate era="ce" calendar="gregorian">1947</unitdate>
   </did>
  <c04 id="ref34582" level="file">
      <did>
         <container label="Box" type="Box">156</container>
         <container label="Folder" type="Folder">3</container>
      </did>
  </c04>
  <c04 id="ref6540" level="file">
      <did>
         <container label="Box" type="Box">156</container>
         <unittitle>Contact prints</unittitle>
      </did>
  </c04>
  <c04 id="ref6606" level="file">
      <did>
         <container label="Box" type="Box">154</container>
         <unittitle>Negatives</unittitle>
      </did>
  </c04>
</c03>


2 commentaires

J'utilise XSLT2, alors je suis allé avec cette solution et cela a fonctionné bien. La seule chose, était que je devais commenter le \ Pour une raison quelconque, il enliquait la duplication des nœuds "unittitle". Merci beaucoup!


Je partage votre hauteur d'opinion sur le livre de Michael Kay. Malheureusement, trop peu de personnes / organisations sont passées à XSLT 2.0.



0
votes

La transformation XSLT 1.0 suivante fait ce que vous recherchez xxx

renvoie xxx

générate-id () = ID de génération (clé (...) [1]) Partie est ce qu'on appelle le groupement Muenchian. Sauf si vous pouvez utiliser XSLT 2.0, c'est la voie à suivre.


0 commentaires

3
votes

Il n'y a pas besoin d'une solution XSLT 2.0 pour ce problème .

Voici une solution XSLT 1.0, qui est plus compacte que la solution XSLT 2.0 actuellement sélectionnée (35 lignes vs. 43 lignes): xxx

Lorsque cette transformation est appliquée sur le document XML initialement fourni, le résultat recherché est produit :: xxx

mise à jour:

Je n'ai pas remarqué que les numéros de conteneur doivent apparaître triés. Maintenant, la solution reflète ceci.


2 commentaires

Votre solution ne trie pas la liste, qui a été demandée dans la question. Facilement corrigé en ajoutant à l'intérieur du XSL: pour chacun boucle.


@Markusk: Merci, je suis habituellement endormi tôt le matin. Besoin également Type de données = "Numéro" Dans ce cas.



1
votes

Une version XSLT 2.0 légèrement plus courte, combinant des approches d'autres réponses. Notez que le tri est alphabétique, de sorte que si les étiquettes "54" et "156" sont trouvées, la sortie sera "156, 54". Si un tri numérique est nécessaire, utilisez Code> au lieu de code>.

<xsl:stylesheet version="2.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output omit-xml-declaration="yes" indent="yes"/> 
    <xsl:strip-space elements="*"/>

    <xsl:template match="node()|@*"> 
        <xsl:copy> 
            <xsl:apply-templates select="node()|@*"/> 
        </xsl:copy> 
    </xsl:template> 

    <xsl:template match="c03/did[not(container)]">
        <xsl:variable name="containers" 
                      select="../c04/did/container[@label='Box'][text()]"/>
        <xsl:copy>
            <xsl:copy-of select="@*"/>
            <xsl:if test="$containers">
                <container label="Box" type="Box">
                    <xsl:for-each select="distinct-values($containers)">
                        <xsl:sort/>
                        <xsl:if test="position() != 1">, </xsl:if>
                        <xsl:value-of select="."/>
                    </xsl:for-each>
                </container> 
            </xsl:if>
            <xsl:apply-templates select="node()"/> 
        </xsl:copy> 
    </xsl:template> 
</xsl:stylesheet>


0 commentaires

1
votes

une solution véritablement xslt 2.0, également assez courte : xxx

note:

  1. L'utilisation de types évite la nécessité de spécifier le type type dans .

  2. L'utilisation du séparateur attribut de


2 commentaires

+1 bien fait. Cependant, savons-nous que l'élément C03 sera la racine? L'affiche n'a indiqué que l'entrée serait "similaire", alors je me sens légèrement plus à l'aise avec des xpaths relatifs (c.-à-d., ../ c04 / conteneur ou peut-être ../*/ conteneur ) au lieu de absolu ( / * / * / * / conteneur ). De cette façon, la feuille de style fonctionne même si l'élément C03 apparaît plus bas dans la structure du document.


@Markusk Nice commentaire à nouveau, et merci pour la uppote! Oui, nous assistons à la manière dont les ops changent constamment la définition de leurs problèmes. Parfois, je suis tenté d'agir en tant que tueur de fortune, mais cela a également un risque en soi. En outre, le code XSLT devient de plus en plus aussi directement liée au XML actuel et donc plus difficile à comprendre. C'est pourquoi, dans des cas comme celui-ci, je préfère généralement rester aussi près que possible du XML posté que possible. J'ai écrit plusieurs fois le code XSLT le plus général, par ex. Le Visualizer / FXSL XPath, mais le but ici est d'être autant spécifique / utile possible. :)