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>
6 Réponses :
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 > p>
L'article de Jeni explique très bien la méthode méchogique pour le mal de la pensée (comme moi)!
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>
J'utilise XSLT2, alors je suis allé avec cette solution et cela a fonctionné bien. La seule chose, était que je devais commenter le \
Je partage votre hauteur d'opinion sur le livre de Michael Kay. Malheureusement, trop peu de personnes / organisations sont passées à XSLT 2.0.
La transformation XSLT 1.0 suivante fait ce que vous recherchez renvoie p> générate-id () = ID de génération (clé (...) [1]) code> Partie est ce qu'on appelle le groupement Muenchian. Sauf si vous pouvez utiliser XSLT 2.0, c'est la voie à suivre. P> p>
Il n'y a pas besoin d'une solution XSLT 2.0 pour ce problème strong>. Voici une solution XSLT 1.0, qui est plus compacte que la solution XSLT 2.0 actuellement sélectionnée forte > (35 lignes vs. 43 lignes): p> Je n'ai pas remarqué que les numéros de conteneur doivent apparaître triés. Maintenant, la solution reflète ceci. P> p>
Votre solution ne trie pas la liste, qui a été demandée dans la question. Facilement corrigé en ajoutant
XSL: pour chacun code> boucle.
@Markusk: Merci, je suis habituellement endormi tôt le matin.
Type de données = "Numéro" Code> Dans ce cas.
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
<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>
note: strong> p> L'utilisation de types évite la nécessité de spécifier le type L'utilisation du séparateur code> attribut code> de
type code> dans
+1 bien fait. Cependant, savons-nous que l'élément C03 code> 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 code> ou peut-être
../*/ conteneur code>) au lieu de absolu (
/ * / * / * / conteneur code>). De cette façon, la feuille de style fonctionne même si l'élément
C03 code> 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. :)
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. :)