Question

Comment puis-je vérifier si une valeur est null ou vide avec XSL ?

Par exemple, si categoryName est vide? J'utilise une pour choisir une construction.

Par exemple:

<xsl:choose>
    <xsl:when test="categoryName !=null">
        <xsl:value-of select="categoryName " />
    </xsl:when>
    <xsl:otherwise>
        <xsl:value-of select="other" />
    </xsl:otherwise>
</xsl:choose>
Était-ce utile?

La solution

test="categoryName != ''"

Modifier : il s'agit de l'interprétation la plus probable, selon moi, de & "; [non] null ou vide &"; comme déduit de la question, y compris son pseudo-code et ma propre première expérience avec XSLT. C’est-à-dire & «Quel est l’équivalent du Java suivant? &« ;:

>
!(categoryName == null || categoryName.equals(""))

Pour plus de détails, par exemple, identifiant distinctement null ou vide, voir la réponse de johnvey ci-dessous et / ou le 'violon' XSLT que j'ai adapté à partir de cette réponse, qui inclut l'option dans le commentaire de Michael Kay ainsi que la sixième possible interprétation.

Autres conseils

En l'absence de toute autre information, je supposerai le code XML suivant:

<group>
    <item>
        <id>item 1</id>
        <CategoryName>blue</CategoryName>
    </item>
    <item>
        <id>item 2</id>
        <CategoryName></CategoryName>
    </item>
    <item>
        <id>item 3</id>
    </item>
    ...
</group>

Un exemple de cas d'utilisation ressemblerait à ceci:

<xsl:for-each select="/group/item">
    <xsl:if test="CategoryName">
        <!-- will be instantiated for item #1 and item #2 -->
    </xsl:if>
    <xsl:if test="not(CategoryName)">
        <!-- will be instantiated for item #3 -->
    </xsl:if>
    <xsl:if test="CategoryName != ''">
        <!-- will be instantiated for item #1 -->
    </xsl:if>
    <xsl:if test="CategoryName = ''">
        <!-- will be instantiated for item #2 -->
    </xsl:if>
</xsl:for-each>

De Élément vide :

Pour tester si la valeur d'un noeud donné est vide

Cela dépend de ce que vous entendez par vide.

  • ne contient aucun nœud enfant: not(node())
  • ne contient aucun contenu de texte: not(string(.))
  • ne contient pas de texte autre que des espaces: not(normalize-space(.))
  • Ne contient rien sauf des commentaires: not(node()[not(self::comment())])

Qu'en est-il?

test="not(normalize-space(categoryName)='')"

Les deux premiers traitent de la valeur null et les deux autres de la chaîne vide.

<xsl:if test="USER/FIRSTNAME">
    USERNAME is not null
</xsl:if>
<xsl:if test="not(USER/FIRSTNAME)">
    USERNAME is null
 </xsl:if>
 <xsl:if test="USER/FIRSTNAME=''">
     USERNAME is empty string
 </xsl:if>
 <xsl:if test="USER/FIRSTNAME!=''">
     USERNAME is not empty string
 </xsl:if>

Dans certains cas, vous voudrez peut-être savoir quand la valeur est spécifiquement nulle, ce qui est particulièrement nécessaire lorsque vous utilisez XML qui a été sérialisé à partir d'objets .NET. Bien que la réponse acceptée fonctionne pour cela, elle renvoie également le même résultat lorsque la chaîne est vide ou vide, c'est-à-dire '', afin que vous ne puissiez pas vous différencier.

<group>
    <item>
        <id>item 1</id>
        <CategoryName xsi:nil="true" />
    </item>
</group>

Vous pouvez donc simplement tester l'attribut.

<xsl:if test="CategoryName/@xsi:nil='true'">
   Hello World.
</xsl:if>

Parfois, il est nécessaire de connaître l'état exact et vous ne pouvez pas simplement vérifier si CategoryName est instancié, car contrairement à Javascript,

<xsl:if test="CategoryName">
   Hello World.
</xsl:if>

Renverra la valeur true pour un élément null.

S'il existe une possibilité que l'élément n'existe pas dans le fichier XML, je vérifierais à la fois que l'élément est présent et que la longueur de la chaîne est supérieure à zéro:

<xsl:choose>
    <xsl:when test="categoryName and string-length(categoryName) &gt; 0">
        <xsl:value-of select="categoryName " />
    </xsl:when>
    <xsl:otherwise>
        <xsl:value-of select="other" />
    </xsl:otherwise>
</xsl:choose>

Je sais que cette question est ancienne, mais entre toutes les réponses, j'en manque une qui constitue une approche commune pour ce cas d'utilisation dans le développement XSLT.

J'imagine que le code manquant dans l'OP ressemble à peu près à ceci:

<xsl:template match="category">
    <xsl:choose>
        <xsl:when test="categoryName !=null">
            <xsl:value-of select="categoryName " />
        </xsl:when>
        <xsl:otherwise>
            <xsl:value-of select="other" />
        </xsl:otherwise>
    </xsl:choose>
</category>

Et que l'entrée ressemble à ceci:

<categories>
    <category>
       <categoryName>Books</categoryName>
    </category>
    <category>
       <categoryName>Magazines</categoryName>
       <categoryName>Periodicals</categoryName>
       <categoryName>Journals</categoryName>
    </category>
    <category>
        <categoryName><!-- please fill in category --></categoryName>
    </category>
    <category>
        <categoryName />
    </category>
    <category />
</categories>

I.e., je suppose qu’il peut y avoir zéro, vide, un ou plusieurs categoryName éléments. Traiter tous ces cas en utilisant des constructions de style xsl:choose, ou en d'autres termes, impérativement, devient vite compliqué (encore plus si les éléments peuvent être à différents niveaux!). Un langage de programmation typique dans XSLT utilise des modèles (d'où le T dans XSLT), qui est une programmation déclarative et non impérative (vous ne dites pas au processeur quoi faire, vous indiquez simplement ce que vous voulez obtenir si certaines conditions sont remplies). Pour ce cas d'utilisation, cela peut ressembler à ceci:

<!-- positive test, any category with a valid categoryName -->
<xsl:template match="category[categoryName[text()]]">
    <xsl:apply-templates />
</xsl:template>

<!-- any other category (without categoryName, "null", with comments etc) -->
<xsl:template match="category">
    <xsl:text>Category: Other</xsl:text>
</xsl:template>

<!-- matching the categoryName itself for easy handling of multiple names -->
<xsl:template match="categoryName">
    <xsl:text>Category: </xsl:text>
    <xsl:value-of select="." />
</xsl:template>

Cela fonctionne (avec n’importe quelle version XSLT), car la première ci-dessus a une priorité plus élevée (elle a un prédicat). Le & Quot; fall-through & Quot; le modèle correspondant, le second, intercepte tout ce qui n’est pas valide. Le troisième prend ensuite en charge la sortie de la valeur categories de manière appropriée.

Notez que dans ce scénario, il n'est pas nécessaire de faire une correspondance spécifique category ou xsl:apply-templates, car le processeur traite automatiquement tous les enfants, sauf indication contraire de notre part (dans cet exemple, les deuxième et troisième modèles ne traiter les enfants, car ils ne contiennent pas null).

Cette approche est plus facilement extensible que l’approche impérative, car elle traite automatiquement plusieurs catégories et elle peut être étendue à d’autres éléments ou exceptions en ajoutant simplement un autre modèle correspondant. Programmation sans if-branches .

Remarque: n'existe pas. Il existe xsi: nil , mais il est rarement utilisé, surtout dans les fichiers non typés. scénarios sans schéma de quelque sorte.

  

Comment puis-je vérifier si une valeur est nulle ou vide avec XSL?

     

Par exemple, si categoryName est vide?

Il s'agit probablement de l'expression XPath la plus simple (celle dans la réponse acceptée fournit un test pour le contraire et serait plus longue si elle était annulée):

not(string(categoryName))

Explication :

L'argument de la fonction not() ci-dessus est false() exactement quand il n'y a pas <=> d'enfant (& "null &") de l'élément de contexte ou du (unique élément) < => l'enfant a une valeur de chaîne - la chaîne vide.

  

J'utilise une construction lors du choix .

     

Par exemple:

<xsl:choose>
    <xsl:when test="categoryName !=null">
        <xsl:value-of select="categoryName " />
    </xsl:when>
    <xsl:otherwise>
        <xsl:value-of select="other" />
    </xsl:otherwise>
</xsl:choose>

Dans XSLT 2.0, utilisez :

<xsl:copy-of select="concat(categoryName,  $vOther[not(string(current()/categoryName))])"/>

Voici un exemple complet :

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

 <xsl:variable name="vOther" select="'Other'"/>

 <xsl:template match="/">
  <xsl:copy-of select="concat(categoryName,$vOther[not(string(current()/categoryName))])"/>
 </xsl:template>
</xsl:stylesheet>

Lorsque cette transformation est appliquée sur le document XML suivant:

<categoryName>X</categoryName>

le résultat souhaité est correct :

X

Appliqué à ce document XML :

<categoryName></categoryName>

ou sur ceci:

<categoryName/>

ou sur ce

<somethingElse>Y</somethingElse>

le résultat correct est généré :

Other

De même, utilisez cette transformation XSLT 1.0 :

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

 <xsl:variable name="vOther" select="'Other'"/>

  <xsl:template match="/">
    <xsl:copy-of select=
    "concat(categoryName,  substring($vOther, 1 div not(string(categoryName))))"/>
  </xsl:template>
</xsl:stylesheet>

Remarque : aucun conditionnel n'est utilisé. Apprenez-en plus sur l’importance d’éviter les constructions conditionnelles dans ce beau cours Pluralsight:

Modèles de conception tactiques dans .NET: flux de contrôle "

Si un noeud n'a pas de valeur disponible dans le XML d'entrée comme ci-dessous xpath,

<node>
    <ErrorCode/>
</node>

La fonction string () est convertie en valeur vide. Donc, cela fonctionne bien:

string(/Node/ErrorCode) =''

Quelque chose comme ça marche pour moi:

<xsl:choose>
  <xsl:when test="string(number(categoryName)) = 'NaN'"> - </xsl:when> 
  <xsl:otherwise> 
    <xsl:number value="categoryName" />
  </xsl:otherwise>
</xsl:choose>

Ou l'inverse:

<xsl:choose>
  <xsl:when test="string(number(categoryName)) != 'NaN'">
    <xsl:number value="categoryName" />
  </xsl:when> 
  <xsl:otherwise> - </xsl:otherwise>
</xsl:choose>

Remarque: Si vous ne cochez pas les valeurs NULL et ne les gérez pas, IE7 renvoie -2147483648 au lieu de NaN.

En fait, j'ai trouvé mieux de simplement tester la longueur de la chaîne, car plusieurs fois le champ n'est pas nul, il est juste vide

  

< xsl: when test = & "string-length" (champ que vous voulez tester) < 1 & "; >

D'après mon expérience, le meilleur moyen est de:

<xsl:when test="not(string(categoryName))">
    <xsl:value-of select="other" />
</xsl:when>
<otherwise>
    <xsl:value-of select="categoryName" />
</otherwise>

Utiliser simple categoryName / text () Un tel test fonctionne correctement sur <categoryName/> et également sur <categoryName></categoryName>.

<xsl:choose>
    <xsl:when test="categoryName/text()">
        <xsl:value-of select="categoryName" />
    </xsl:when>
    <xsl:otherwise>
        <xsl:value-of select="other" />
    </xsl:otherwise>
</xsl:choose>
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top