Compruebe si una cadena es nula o está vacía en XSLT
null xslt-1.0 (14)
¿Cómo puedo verificar si un valor es nulo o está vacío con XSL ?
Por ejemplo, si categoryName
está vacío? Estoy usando una construcción al elegir .
Por ejemplo:
<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>
¿Cómo puedo verificar si un valor es nulo o está vacío con XSL?
Por ejemplo, si
categoryName
está vacío?
Esta es probablemente la expresión XPath más simple (la respuesta aceptada proporciona una prueba de lo contrario, y sería más larga si se negara):
not(string(categoryName))
Explicación :
El argumento de la función not()
anterior es false()
exactamente cuando no hay un niño de CategoryName ("null") del elemento de contexto, o el hijo de categoryName
(solo uno) tiene un valor de cadena, la cadena vacía.
Estoy usando una construcción al elegir .
Por ejemplo:
<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>
En XSLT 2.0 use :
<xsl:copy-of select="concat(categoryName, $vOther[not(string(current()/categoryName))])"/>
Aquí hay un ejemplo 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>
Cuando esta transformación se aplica en el siguiente documento XML:
<categoryName>X</categoryName>
Se produce el resultado deseado, correcto :
X
Cuando se aplica en este documento XML :
<categoryName></categoryName>
o en este:
<categoryName/>
o en este
<somethingElse>Y</somethingElse>
Se produce el resultado correcto :
Other
Del mismo modo, utilice esta transformación 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>
Tenga en cuenta : No se utilizan condicionales en absoluto. Aprenda más sobre la importancia de evitar construcciones condicionales en este agradable curso de Pluralsight:
¿Qué pasa?
test="not(normalize-space(categoryName)='''')"
A falta de cualquier otra información, asumiré el siguiente 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 ejemplo de caso de uso sería:
<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>
Algo como esto funciona para mí:
<xsl:choose>
<xsl:when test="string(number(categoryName)) = ''NaN''"> - </xsl:when>
<xsl:otherwise>
<xsl:number value="categoryName" />
</xsl:otherwise>
</xsl:choose>
O al revés:
<xsl:choose>
<xsl:when test="string(number(categoryName)) != ''NaN''">
<xsl:number value="categoryName" />
</xsl:when>
<xsl:otherwise> - </xsl:otherwise>
</xsl:choose>
Nota: Si no verifica valores nulos o maneja valores nulos, IE7 devuelve -2147483648 en lugar de NaN.
Del elemento vacío :
Para probar si el valor de un determinado nodo está vacío
Depende de lo que quieras decir con vacío.
- No contiene nodos secundarios:
not(node())
- No contiene contenido de texto:
not(string(.))
- No contiene texto que no sea espacios en blanco:
not(normalize-space(.))
- No contiene nada, excepto los comentarios:
not(node()[not(self::comment())])
En algunos casos, es posible que desee saber cuándo el valor es específicamente nulo, lo que es particularmente necesario cuando se utiliza XML que se ha serializado desde objetos .NET. Si bien la respuesta aceptada funciona para esto, también devuelve el mismo resultado cuando la cadena está en blanco o vacía, es decir, '''', por lo que no puede diferenciarse.
<group>
<item>
<id>item 1</id>
<CategoryName xsi:nil="true" />
</item>
</group>
Así que simplemente puedes probar el atributo.
<xsl:if test="CategoryName/@xsi:nil=''true''">
Hello World.
</xsl:if>
A veces es necesario conocer el estado exacto y no puede simplemente verificar si se ha creado una instancia de CategoryName, porque a diferencia de Javascript
<xsl:if test="CategoryName">
Hello World.
</xsl:if>
Devolverá true para un elemento nulo.
Las dos primeras se ocupan del valor nulo y la segunda se ocupa de la cadena vacía.
<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>
Por mi experiencia la mejor manera es:
<xsl:when test="not(string(categoryName))">
<xsl:value-of select="other" />
</xsl:when>
<otherwise>
<xsl:value-of select="categoryName" />
</otherwise>
Realmente lo encontré mejor solo probando la longitud de la cadena ya que muchas veces el campo no es nulo, simplemente está vacío
<xsl: cuando test = "string-length (field-you-want-to-test) <1">
Sé que esta pregunta es antigua, pero entre todas las respuestas, echo de menos una que es un enfoque común para este caso de uso en el desarrollo de XSLT.
Me estoy imaginando que el código que falta en el OP se ve algo como esto:
<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>
Y que la entrada se ve algo como esto:
<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>
Es decir, asumo que puede haber cero, vacíos, elementos simples o múltiples de categoryName
. Para hacer frente a todos estos casos con xsl:choose
las construcciones de estilo, o en otras palabras, de manera imperativa, se está ensuciando rápidamente (más aún si los elementos pueden estar en diferentes niveles). Un lenguaje de programación típico en XSLT es el uso de plantillas (por lo tanto, la T en XSLT), que es programación declarativa, no imperativa (no le dice al procesador qué hacer, simplemente le dice a la salida que desea obtener si se cumplen ciertas condiciones). Para este caso de uso, puede verse algo como lo siguiente:
<!-- 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>
Esto funciona (con cualquier versión XSLT), porque la primera de arriba tiene una precedencia más alta (tiene un predicado). La plantilla de coincidencia de "caída directa", la segunda, detecta cualquier cosa que no sea válida. El tercero luego se encarga de emitir el valor de categoryName
de una manera adecuada.
Tenga en cuenta que en este escenario no es necesario que coincida específicamente con categories
o category
, porque el procesador procesará automáticamente todos los hijos, a menos que le indiquemos lo contrario (en este ejemplo, la segunda y tercera plantilla no procesan más a los hijos, porque hay no xsl:apply-templates
en ellos).
Este enfoque es más fácil de extender que el enfoque imperativo, ya que se ocupa de forma automática de múltiples categorías y se puede expandir para otros elementos o excepciones simplemente agregando otra plantilla coincidente. Programación sin if-sucursales .
Nota: no hay tal cosa como null
en XML. Hay xsi:nil , pero eso se usa raramente, especialmente en escenarios sin tipo sin un esquema de algún tipo.
Si existe la posibilidad de que el elemento no exista en el XML, probaría que el elemento está presente y que la longitud de la cadena es mayor que cero:
<xsl:choose>
<xsl:when test="categoryName and string-length(categoryName) > 0">
<xsl:value-of select="categoryName " />
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="other" />
</xsl:otherwise>
</xsl:choose>
Si un nodo no tiene un valor disponible en el xml de entrada como debajo de xpath,
<node>
<ErrorCode/>
</node>
La función string () se convierte en un valor vacío. Así que esto funciona bien:
string(/Node/ErrorCode) =''''
Use categoryName / text () simple. Esta prueba funciona bien en <categoryName/>
y también en <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>
test="categoryName != ''''"
Edición : Esto cubre la interpretación más probable, en mi opinión, de "[no] nulo o vacío" como se deduce de la pregunta, incluido su pseudocódigo y mi propia experiencia temprana con XSLT. Es decir, "¿Cuál es el equivalente de la siguiente Java?":
!(categoryName == null || categoryName.equals(""))
Para obtener más detalles, por ejemplo, identificando claramente nulo frente a vacío, vea la respuesta de johnvey a continuación y / o el ''violín'' de XSLT que he adaptado de esa respuesta, que incluye la opción en el comentario de Michael Kay, así como la sexta interpretación posible.