Domanda

Come posso verificare se un valore è nullo o vuoto con XSL ?

Ad esempio, se categoryName è vuoto? Sto usando un quando scelgo il costrutto.

Ad esempio:

<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>
È stato utile?

Soluzione

test="categoryName != ''"

Modifica : riguarda l'interpretazione più probabile, a mio avviso, di " [not] null o empty " come dedotto dalla domanda, incluso il suo pseudo-codice e la mia prima esperienza con XSLT. Ad esempio, & Quot; Qual è l'equivalente del seguente Java? & Quot ;:

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

Per ulteriori dettagli, ad es. per identificare distintamente null vs empty, vedere la risposta di johnvey in basso e / o il 'violino' XSLT Mi sono adattato da quella risposta, che include l'opzione nel commento di Michael Kay e la sesta possibile interpretazione.

Altri suggerimenti

In assenza di altre informazioni, assumerò il seguente XML:

<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 esempio di utilizzo potrebbe apparire come:

<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>

Da Elemento vuoto :

Per verificare se il valore di un determinato nodo è vuoto

Dipende da cosa intendi per vuoto.

  • Non contiene nodi figlio: not(node())
  • Non contiene contenuto testuale: not(string(.))
  • Non contiene testo diverso dagli spazi bianchi: not(normalize-space(.))
  • Non contiene nulla tranne i commenti: not(node()[not(self::comment())])

Che dire?

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

I primi due trattano con valore nullo e i secondi due trattano con stringa vuota.

<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>

In alcuni casi, potresti voler sapere quando il valore è specificamente nullo, il che è particolarmente necessario quando si utilizza XML che è stato serializzato da oggetti .NET. Mentre la risposta accettata funziona per questo, restituisce anche lo stesso risultato quando la stringa è vuota o vuota, vale a dire '', quindi non è possibile differenziare.

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

Quindi puoi semplicemente testare l'attributo.

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

A volte è necessario conoscere lo stato esatto e non puoi semplicemente controllare se CategoryName è istanziato, perché a differenza di dire Javascript

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

Restituirà vero per un elemento null.

Se esiste la possibilità che l'elemento non esista nell'XML, verificherei sia che l'elemento sia presente sia che la lunghezza della stringa sia maggiore di zero:

<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>

So che questa domanda è vecchia, ma tra tutte le risposte, mi manca una che è un approccio comune per questo caso d'uso nello sviluppo di XSLT.

Sto immaginando che il codice mancante dall'OP assomigli a questo:

<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>

E che l'input è simile al seguente:

<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>

Cioè, suppongo che ci possano essere zero, vuoti, singoli o multipli categoryName elementi. Affrontare tutti questi casi usando costrutti in stile xsl:choose, o in altre parole, in modo imperativo, sta rapidamente diventando disordinato (ancora di più se gli elementi possono essere a livelli diversi!). Un tipico linguaggio di programmazione in XSLT sta usando i template (da qui la T in XSLT), che è programmazione dichiarativa, non imperativa (non dite al processore cosa fare, dite semplicemente cosa volete output se sono soddisfatte determinate condizioni). Per questo caso d'uso, potrebbe essere simile al seguente:

<!-- 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>

Funziona (con qualsiasi versione XSLT), perché la prima sopra ha una precedenza più alta (ha un predicato). Il & Quot; fall-through & Quot; il modello corrispondente, il secondo, rileva tutto ciò che non è valido. Il terzo si occupa quindi di fornire il valore categories in modo corretto.

Nota che in questo scenario non è necessario abbinare in modo specifico category o xsl:apply-templates, poiché il processore elaborerà automaticamente tutti i bambini, a meno che non lo diciamo diversamente (in questo esempio, il secondo e il terzo modello non approfondiscono ulteriormente elabora i bambini, perché non ci sono null in essi).

Questo approccio è più facilmente estensibile di quello imperativo, perché si occupa automaticamente di più categorie e può essere espanso per altri elementi o eccezioni semplicemente aggiungendo un altro modello di corrispondenza. Programmazione senza if-branch .

Nota: non esiste qualcosa come <=> in XML. C'è xsi: nil , ma che viene usato raramente, specialmente raramente in non tipizzato scenari senza uno schema di qualche tipo.

  

Come posso verificare se un valore è nullo o vuoto con XSL?

     

Ad esempio, se categoryName è vuoto?

Questa è probabilmente l'espressione XPath più semplice (quella nella risposta accettata fornisce un test per il contrario e sarebbe più lunga, se negata):

not(string(categoryName))

Spiegazione :

L'argomento della funzione not() sopra è false() esattamente quando non c'è <=> figlio (" null ") dell'elemento di contesto, o il (singolo tale) < => child ha un valore stringa: la stringa vuota.

  

Sto usando un quando scelgo il costrutto.

     

Ad esempio:

<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>

In XSLT 2.0 usa :

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

Ecco un esempio completo :

<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>

Quando questa trasformazione viene applicata al seguente documento XML:

<categoryName>X</categoryName>

viene prodotto il risultato desiderato desiderato :

X

Se applicato su questo documento XML :

<categoryName></categoryName>

o su questo:

<categoryName/>

o su questo

<somethingElse>Y</somethingElse>

viene prodotto il risultato corretto :

Other

Allo stesso modo, usa questa XSLT 1.0 trasformazione:

<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>

Nota : non vengono utilizzati affatto condizionali. Scopri di più sull'importanza di evitare costrutti condizionali in questo bel corso Pluralsight:

quot; Modelli di progettazione tattica in .NET: flusso di controllo "

Se un nodo non ha alcun valore disponibile nell'input xml come sotto xpath,

<node>
    <ErrorCode/>
</node>
La funzione

string () viene convertita in valore vuoto. Quindi funziona bene:

string(/Node/ErrorCode) =''

Qualcosa del genere funziona per me:

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

O viceversa:

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

Nota: se non si controllano valori null o non si gestiscono valori null, IE7 restituisce -2147483648 anziché NaN.

In realtà l'ho trovato meglio solo testando la lunghezza della stringa poiché molte volte il campo non è nullo, è solo vuoto

  

< xsl: when test = " string-length (field-you-want-to-test) < 1 " >

Per la mia esperienza il modo migliore è:

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

Usa semplice nomeCategoria / testo () Tale test funziona bene su <categoryName/> e anche <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>
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top