web-dev-qa-db-fra.com

Vérifier si le noeud avec l'attribut est égal à la valeur existe

J'ai la variable XSLT suivante: 

<xsl:variable name="superid" select="/contentdata/id"/>

De plus, j'ai un nœud avec des sous-nœuds:

<nodes>
    <node name="foo" id="bar" />
    <node name="john" id="doe" />
    <node name="jane" id="tarzan" />
</nodes>

Maintenant, j'aimerais vérifier si un nœud avec un attribut id égal à superid existe.

J'ai essayé ce qui suit (ce qui ne fonctionne évidemment pas):

<xsl:if test="/nodes/node[@id = $superid]">Yes, Sir!</xsl:if>
10
Helge

Utilisation :

boolean(/nodes/node/@id = $superid)

Voici une transformation complète, montrant cela en action :

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output method="text"/>
 <xsl:strip-space elements="*"/>

 <xsl:variable name="vDoe" select="'doe'"/>
 <xsl:variable name="vXyz" select="'xyz'"/>

 <xsl:template match="/">
     id attribute with value "doe' exists: <xsl:text/>
     <xsl:value-of select="boolean(/nodes/node/@id = $vDoe)"/>
==========
     id attribute with value "xyz' exists: <xsl:text/>
     <xsl:value-of select="boolean(/nodes/node/@id = $vXyz)"/>
 </xsl:template>
</xsl:stylesheet>

lorsque cette transformation est appliquée sur le document XML fourni :

<nodes>
    <node name="foo" id="bar" />
    <node name="john" id="doe" />
    <node name="jane" id="tarzan" />
</nodes>

le résultat recherché est correct :

     id attribute with value "doe' exists: true
==========
     id attribute with value "xyz' exists: false
15
Dimitre Novatchev

Ce que vous avez semble fonctionner pour moi (.Net 3.5) - selon ici .

J'ai essayé de recréer votre xslt:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                version="1.0"
                xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                >
    <xsl:output omit-xml-declaration="yes" method="xml" version="1.0" indent="yes" />

    <xsl:template match="/xml">
        <xml>
            <xsl:apply-templates select="contentdata/id" />
        </xml>
    </xsl:template>

    <xsl:template match="id">
        <Result>
        <xsl:variable name="superid" select="."/>
        <SearchFor>
            <xsl:value-of select="$superid"/>
        </SearchFor>
        <IsPresent>
            <xsl:if test="/xml/nodes/node[@id = $superid]">Node is present</xsl:if>
        </IsPresent>
    </Result>
    </xsl:template>

</xsl:stylesheet>

Étant donné le xml:

<xml>
    <contentdata>
        <id>doe</id>
        <id>unobtanium</id>
    </contentdata>
    <nodes>
        <node name='foo' id='bar' />
        <node name='john' id='doe' />
        <node name='jane' id='tarzan' />
    </nodes>
</xml>

Sortie:

<xml xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <Result>
        <SearchFor>doe</SearchFor>
        <IsPresent>Node is present</IsPresent>
    </Result>
    <Result>
        <SearchFor>unobtanium</SearchFor>
        <IsPresent />
    </Result>
</xml>
4
StuartLC

Si vous utilisez l'expression xpath/nœuds/nœud [@id = $ superid] "> , cela chercherait un nœud racine de nœuds dans votre document XML. semble impliquer nœuds est juste un nœud dans votre document, pas nécessairement l'élément racine. Essayez ceci à la place.

<xsl:if test="//nodes/node[@id = $superid]">Yes, Sir!</xsl:if>

La double barre oblique sélectionne les nœuds du document où qu'ils se trouvent dans la hiérarchie, pas seulement le nœud de niveau supérieur.

3
Tim C

Cela devrait fonctionner comme prévu. L'une de vos expressions (dans la variable select ou dans l'attribut test) ne doit pas sélectionner ce que vous pensez être. (Vous n'avez pas fourni votre contribution complète, il est donc difficile d'aider là-bas.) 

Notez quelques points à propos de xsl:if:

  • Tout d’abord, voyez cette partie de la spécification XSLT (l’accent est mis sur moi):

    L'élément xsl: if a un attribut test, qui spécifie un expression. Le contenu est un modèle. L'expression est évaluée et l'objet résultant est converti en un booléen comme par un appel à fonction booléenne. Si le résultat est true, le modèle de contenu est instancié; sinon, rien n'est créé.

  • Alors, comment un appel à la fonction boolean fonctionnerait-il sur votre entrée? Voir cette partie de la spécification XPath (encore une fois, c'est moi qui souligne):

    La fonction booléenne convertit son argument en booléen comme suit:

    • un nombre est vrai si et seulement si ce n'est ni zéro positif ni négatif, ni NaN

    • un ensemble de nœuds est vrai si et seulement s'il n'est pas vide

    • une chaîne est vraie si et seulement si sa longueur est différente de zéro

    • un objet d'un type autre que les quatre types de base est converti en un booléen d'une manière qui dépend de ce type

Ainsi, si /contentdata/id sélectionne réellement une id pour laquelle /nodes/node[@id = $superid] renvoie un ensemble de nœuds non vide, le corps de xsl:if doit alors s'exécuter.

1
Wayne Burkett