XSLT 1.0 variante distincte des valeurs
J'ai une transformation XSLT dans lequel j'ai créer (à partir de la donnée d'entrée) intermédiaire des variables comme la suivante (codée en dur dans l'exemple, mais de nature dynamique):
<xsl:variable name="variableX">
<ValidCode CodePart="CP1" Code="C1"/>
<ValidCode CodePart="CP2" Code="C2"/>
<ValidCode CodePart="CP1" Code="C3"/>
<ValidCode CodePart="CP2" Code="C4"/>
<ValidCode CodePart="CP2" Code="C5"/>
</xsl:variable>
Je souhaite faire une boucle sur les différentes occurrences de CodePart valeurs. En XSLT 2.0, c'est facile:
<xsl:for-each select="distinct-values($variableX/ValidCode/@CodePart)">...</xsl:for-each>
Mais comment mieux le faire en XSLT 1.0?
Notez que je ne peux pas utiliser une clé, comme il est déterminé de façon dynamique variable et ne fait pas partie du fichier d'entrée.
Mon fichier d'entrée contient une liste de toutes les parties de code comme suit:
<root>
<CodePart><value>CP1</value></CodePart>
<CodePart><value>CP2</value></CodePart>
<CodePart><value>CP3</value></CodePart>
</root>
Alors j'ai pensé à boucler sur //CodePart/value
au lieu de cela, s'assurer de l'unicité pour les débutants. Mais ensuite, j'ai besoin d'une expression Xpath qui comprend l'état
"valeur se produit dans le node-set de tous les $variableX/ValidCode/@CodePart valeurs"
et d'utiliser quelque chose comme
<xsl:for-each select="//CodePart[..condition..]/value">...</xsl:for-each>
Est-il une forme simple de l'expression Xpath je suis à la recherche d'?
Ou est une autre approche préférable?
I can't use a key, as it's a dynamically determined variable and not part of the input file
" -- n'est pas vrai. En fait, le plus simple et efficace solution à ce problème utilise des clés.OriginalL'auteur Maestro13 | 2012-06-19
Vous devez vous connecter pour publier un commentaire.
Je ne pense pas que vous pouvez utiliser directement un XPath - mais vous devriez être en mesure de vérifier uniquement les valeurs valides comme ceci:
ou plus simplement (merci pour les commentaires):
Si
$variableX
n'est pas un ensemble de nœuds, mais un fragment XML, il doit être converti en un ensemble de nœuds, - c'est dépendant de l'implémentation, à l'aide de Microsoft processeurs:xsl:if
déclaration comme une condition sur//CodePart/value
? Quelque chose comme<xsl:for-each select="//CodePart/value[$variableX/ValidCode[@CodePart=current()]]">
(qui ne fait pas l'affaire, mais peut-être fermer)?Non, je ne pense pas que c'est possible: tout ce que vous écrivez directement à l'intérieur de la deuxième
[...]
est par rapport à$variable/ValidCode
- de sorte que vous ne serez pas en mesure d'accéder à la valeur que vous avez besoin, c'est par rapport à l'extérieur//CodePart/value
- d'où la nécessité d'une variable.Eh bien, je ne pense pas que vous avez besoin de la variable:
<xsl:if test="$variableX/ValidCode[@CodePart=current()]">
fonctionne tout aussi bien.Cela ne fonctionne pas dans XSLT 1.0, car il n'est pas autorisé à utiliser un résultat fragment d'arbre dans une expression de chemin.
merci, j'ai corrigé la réponse
OriginalL'auteur MiMo
Ce n'est tout simplement pas vrai.
Voici une courte, simple et la plus efficace de la solution à l'aide des touches (btw, ne pas utiliser toutes les instructions conditionnelles ou
xsl:for-each
à tous 🙂 ):Lorsque cette transformation est appliquée sur n'importe quel document XML (non utilisé), le voulait, résultat correct est produit:
Explication:
Comme spécifié dans le W3C XSLT 1.0 Recommandation:
Dans la solution fournie nous n'avons même pas utiliser cette possibilité-à la fois le nœud de contexte et de l'extrait clés sont de la même document, l'arbre temporaire contenues dans
$vCodes
.Encore là, il est précisé qu'une clé peut être utilisée pour plus d'un document:
À mettre en mots simples: l'indexation est effectuée sur la document actuel (le document qui contient le contexte (en cours) nœud).
J'ai dû tordre certaines choses autour de vous (
ValidCode
nœuds également se produire dans le fichier d'entrée, donc j'ai dû ajouter une distinction au niveau de la variable) mais je l'ai eu à travailler tous droit. La Performance ne semble pas être différent, donc, pourriez-vous expliquer pourquoi la solution clé serait plus rapide, ayant un faible niveau de complexité? Ou sont les niveaux de complexité de la même (aussi loin que je peux voir, la clé est d'être ré-évaluée pour chaque nouveau lancement du modèle où la variable est reconstucted - par conséquent, similaire à laxsl:if
de la construction?).De hachage la fonction de recherche est
O(N/k)
oùk
est le nombre d'éléments différents. Sik
est ~N
la complexité du temps est ~O(1)
. Un dé-duplication algorithme qui compare chaque élément de ses éléments précédents est O(N^2). Cela dit, siN
est un petit nombre, il peut y avoir peu ou pas de différence de performances -- le big O notation fait sens pour les grands-assez de valeurs de N. Habituellement la différence entre un O(N) et O(N^2) peuvent être mesurés, si les deux algorithmes sont exécutés pourN
et puis pour10*N
. Le O(N) on va prendre 10 fois plus de temps, tandis que le O(N^2) on prend 100 fois plus de temps.OriginalL'auteur Dimitre Novatchev
Dans XPath 1.0, vous pouvez émuler le
distinct-values
fonction par la recherche pour les précédentes frères et sœurs, avec la même valeur.J'ai simplifié de votre premier document de cette sorte qu'il peut être plus facile à reproduire (sans même l'aide de XSLT):
Ensuite, l'expression XPath suivante permettra de sélectionner d'un seul
CodePart
attribut avec chacune des valeurs qui se produisent dans le document:Donc, la condition de la
CodePart
attributs pour sélectionner c'est qu'il n'y a pas de précédent, de frère, de la<ValidCode>
élément dontCodePart
attribut a la même valeur que la actuellement examinés (sélectionné)CodePart
attribut.Ok, désolé. Peut-être que je n'ai pas très bien compris ce que tu voulais dire par dynamique de données. C'est la même solution que celle illustrée par Filburt (les autres non sélectionné), de toute façon.
Pas exactement, il a quitté le fichier d'entrée et la variable intacte. Et ce n'est pas que je n'apprécie pas de son et de votre effort que je n'ai pas de sélectionner sa réponse et oui Filburt n'inclut pas le noeud nécessaire-fonction set() pour la création d'un node-set à partir d'un fichier au format RTF où MiMo oublié de le faire.
En effet, j'ai l'habitude de minimiser les échantillons de rendre les problèmes et les solutions plus facilement reproductible et plus généralement applicable. Sorr si cette confusion questions pour vous :-/
OriginalL'auteur O. R. Mapper
Une façon de résoudre ce (sans clé) serait de trier et de test contre
preceding-sibling
OriginalL'auteur Filburt
À l'aide de
node-set()
fonction, par exemple avec saxon:xsl:for-each
équivalents de de ce avec la msxsl node-set en fonction, et je pense que ça ne fonctionnera pas car le node-set est un ensemble de valeurs et de la . est juste une valeur. Avez-vous essayez d'exécuter un test?Yespica. Ça fonctionne très bien. Veuillez donner des commentaires sinon je dois supprimer cette réponse.
OriginalL'auteur Emiliano Poggi