Pergunta

Como posso verificar se um valor é nulo ou vazio com XSL ?

Por exemplo, se categoryName está vazio? Eu estou usando um ao escolher construção.

Por exemplo:

<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>
Foi útil?

Solução

test="categoryName != ''"

Editar : essa cobre a interpretação mais provável, na minha opinião, de "nulo [não] ou vazio", como inferida a partir da causa, incluindo pseudo-código a sua ea minha própria experiência inicial com XSLT . Ou seja, "O que é o equivalente do seguinte Java?":

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

Para mais detalhes, por exemplo, claramente identificar nulo vs. vazio, consulte resposta de johnvey abaixo e / ou o XSLT 'violino' eu adaptei a partir dessa resposta, que inclui a opção no comentário de Michael Kay, bem como o sexto possível interpretação.

Outras dicas

Ausente de qualquer outra informação, eu vou assumir o seguinte 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>

Um caso de uso de exemplo seria parecido com:

<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 Esvaziar Elemento :

Para testar se o valor de um determinado nó está vazio

Depende do que você quer dizer com vazia.

  • Não contém nós filho: not(node())
  • Não contém conteúdo de texto: not(string(.))
  • Não contém texto diferente de espaço em branco: not(normalize-space(.))
  • Contém nada, exceto comentários: not(node()[not(self::comment())])

Sobre o quê?

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

Os dois primeiros lidam com valor nulo e dois segundo contrato com a cadeia vazia.

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

Em alguns casos, você pode querer saber quando o valor é especificamente nulo, o que é particularmente necessário quando se utiliza XML que tem sido serializado de objetos .NET. Enquanto a resposta aceita trabalha para isso, ele também retorna o mesmo resultado quando a corda está em branco ou vazio, ou seja, '', então você não pode diferenciar.

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

Então você pode simplesmente testar o atributo.

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

Às vezes é necessário saber o estado exato e você não pode simplesmente verificar se CategoryName é instanciado, porque digamos ao contrário de Javascript

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

retornará verdadeiro para um elemento nulo.

Se houver uma possibilidade de que o elemento não existe no XML que eu iria testar tanto que o elemento está presente e que a cadeia de comprimento é maior do que 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>

Eu sei que esta questão é antiga, mas entre todas as respostas, eu sinto falta de um que é uma abordagem comum para este caso de uso no desenvolvimento XSLT.

Eu estou imaginando que o código ausente do OP é algo como isto:

<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 que a aparência de entrada algo como isto:

<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., Presumo que não pode ser zero, vazio, simples ou múltiplos elementos categoryName. Para lidar com todos esses casos usando construções de estilo xsl:choose, ou em outras palavras, imperativamente, é rapidamente ficar confuso (ainda mais se elementos podem estar em diferentes níveis!). A linguagem de programação típica em XSLT está usando templates (daí o T em XSLT), que é programação declarativa, não imperativo (você não diga o processador o que fazer, você acabou de dizer o que você quer saída se forem respeitadas determinadas condições). Para este caso de uso, que pode ser algo como o seguinte:

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

Isso funciona (com qualquer versão XSLT), porque o primeiro acima tem uma precedência maior (tem um predicado). A "queda-through" modelo de correspondência, o segundo, pega qualquer coisa que não é válido. O terceiro, em seguida, cuida de produzir o valor categoryName em um bom caminho.

Note que, neste cenário, não há necessidade de combinar specifially categories ou category, porque o processador irá processar automaticamente todas as crianças, a menos que diga que de outra forma (neste exemplo, o segundo eo terceiro modelo não tratará as crianças, porque não há xsl:apply-templates neles).

Esta abordagem é mais facilmente extensíveis, em seguida, a abordagem imperativa, porque automically lida com várias categorias e pode ser expandida para outros elementos ou exceções apenas adicionando outro modelo correspondente. Programação sem se-ramos .

Nota: não existe tal coisa como null em XML. Há xsi: nil , mas que raramente é usado, especialmente raramente em untyped cenários sem um esquema de algum tipo.

Como posso verificar se um valor é nulo ou vazio com XSL?

Por exemplo, se categoryName está vazio?

Esta é provavelmente a expressão XPath simples (aquele em resposta aceita fornece um teste para o oposto, e seria mais longo, se negada):

not(string(categoryName))

Explicação :

O argumento para a função not() acima é false() exatamente quando não há nenhuma criança categoryName ( "null") do item de contexto, ou o (single tal) criança categoryName tem valor string -. A cadeia vazia

Eu estou usando um ao escolher construção.

Por exemplo:

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

Em XSLT 2.0 uso :

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

Aqui está um exemplo 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 esta transformação é aplicada no seguinte documento XML:

<categoryName>X</categoryName>

o queria, resultado correto é produzido :

X

Quando aplicado no presente documento XML :

<categoryName></categoryName>

ou sobre isso:

<categoryName/>

ou neste

<somethingElse>Y</somethingElse>

o resultado correto é produzido :

Other

Da mesma forma, usar este XSLT 1.0 transformação:

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

Do nota : Não condicionais são usados ??em tudo. Saiba mais sobre a importância de evitar construções condicionais em Nice Pluralsight curso:

"< strong> Tactical design Patterns em .NET: Controle de Fluxo "

Se um nó não tem nenhum valor disponível no xml de entrada como abaixo xpath,

<node>
    <ErrorCode/>
</node>

string () converte função em valor vazio. Então, isso funciona bem:

string(/Node/ErrorCode) =''

Algo como isso funciona para mim:

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

Ou o contrário:

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

. Nota: Se você não verificar os valores nulos ou valores nulos Pega, retornos IE7 em vez de -2147483648 NaN

Na verdade, eu achei melhor apenas testando para comprimento da corda uma vez que muitas vezes o campo não é nulo, apenas esvaziar

Por minha experiência, a melhor maneira é:

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

Use simples categoryName / text () Esse teste funciona bem no <categoryName/> e também <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>
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top