其他分享
首页 > 其他分享> > Check if a string is null or empty in XSLT

Check if a string is null or empty in XSLT

作者:互联网

多条件查询

string.Format("/root/deviceList//item/guid[{0}]", strBuilder.ToString())
"/root/deviceList//item/guid[text()=\"h\" or text()=\"a\" or text()=\"c\"]"

 

Check if a string is null or empty in XSLT

Ask Question Asked 10 years, 10 months ago Active 2 years, 1 month ago Viewed 506k times 323

How can I check if a value is null or empty with XSL?

For example, if categoryName is empty? I'm using a when choosing construct.

For example:

<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>
    shareimprove this question edited Jul 25 '14 at 17:35 Isaac G Sivaa 1,15133 gold badges1313 silver badges3232 bronze badges asked May 5 '09 at 16:45 raklos 24.8k5252 gold badges165165 silver badges267267 bronze badges add a comment

14 Answers

activeoldestvotes 318  
test="categoryName != ''"

Edit: This covers the most likely interpretation, in my opinion, of "[not] null or empty" as inferred from the question, including it's pseudo-code and my own early experience with XSLT. I.e., "What is the equivalent of the following Java?":

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

For more details e.g., distinctly identifying null vs. empty, see johnvey's answer below and/or the XSLT 'fiddle' I've adapted from that answer, which includes the option in Michael Kay's comment as well as the sixth possible interpretation.

shareimprove this answer edited Jan 10 '18 at 10:33 bluish 20.9k2121 gold badges103103 silver badges158158 bronze badges answered May 5 '09 at 16:53 steamer25 7,75011 gold badge2323 silver badges3232 bronze badges show 4 more comments <iframe data-google-container-id="2" data-is-safeframe="true" data-load-complete="true" frameborder="0" height="90" id="google_ads_iframe_/248424177/stackoverflow.com/mlb/question-pages_0" marginheight="0" marginwidth="0" scrolling="no" src="https://tpc.googlesyndication.com/safeframe/1-0-37/html/container.html" title="3rd party ad content" width="728"></iframe> 269

Absent of any other information, I'll assume the following 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>

A sample use case would look like:

<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>
shareimprove this answer edited May 6 '09 at 18:01 Dirk Vollmar 153k5151 gold badges238238 silver badges293293 bronze badges answered May 5 '09 at 17:06 johnvey 4,72811 gold badge1515 silver badges1313 bronze badges add a comment 67

From Empty Element:

To test if the value of a certain node is empty

It depends on what you mean by empty.

shareimprove this answer edited Dec 8 '15 at 13:49 Mads Hansen 48k1111 gold badges100100 silver badges129129 bronze badges answered May 5 '09 at 16:53 Chris Doggett 16.6k44 gold badges5353 silver badges8484 bronze badges add a comment 22

What about?

test="not(normalize-space(categoryName)='')"
shareimprove this answer answered Dec 2 '11 at 15:05 helcim 71099 silver badges2525 bronze badges add a comment 9

First two deal with null value and second two deal with empty string.

<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>
shareimprove this answer answered Aug 10 '12 at 12:58 Aleksandar Borkovac 13333 silver badges88 bronze badges add a comment 7

In some cases, you might want to know when the value is specifically null, which is particularly necessary when using XML which has been serialized from .NET objects. While the accepted answer works for this, it also returns the same result when the string is blank or empty, i.e. '', so you can't differentiate.

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

So you can simply test the attribute.

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

Sometimes it's necessary to know the exact state and you can't simply check if CategoryName is instantiated, because unlike say Javascript

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

Will return true for a null element.

shareimprove this answer answered Aug 12 '11 at 8:26 DustJones 7111 silver badge22 bronze badges add a comment 6

I know this question is old, but between all the answers, I miss one that is a common approach for this use-case in XSLT development.

I am imagining that the missing code from the OP looks something like this:

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

And that the input looks something like this:

<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., I assume there can be zero, empty, single or multiple categoryName elements. To deal with all these cases using xsl:choose-style constructs, or in other words, imperatively, is quickly getting messy (even more so if elements can be at different levels!). A typical programming idiom in XSLT is using templates (hence the T in XSLT), which is declarative programming, not imperative (you don't tell the processor what to do, you just tell what you want output if certain conditions are met). For this use-case, that can look something like the following:

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

This works (with any XSLT version), because the first one above has a higher precedence (it has a predicate). The "fall-through" matching template, the second one, catches anything that is not valid. The third one then takes care of outputting the categoryName value in a proper way.

Note that in this scenario there is no need to specifially match categories or category, because the processor will automatically process all children, unless we tell it otherwise (in this example, the second and third template do not further process the children, because there is no xsl:apply-templates in them).

This approach is more easily extendible then the imperative approach, because it automically deals with multiple categories and it can be expanded for other elements or exceptions by just adding another matching template. Programming without if-branches.

Note: there is no such thing as null in XML. There is xsi:nil, but that is rarely used, especially rarely in untyped scenarios without a schema of some sort.

shareimprove this answer edited Jan 21 '16 at 2:56 Dimitre Novatchev 221k2626 gold badges262262 silver badges384384 bronze badges answered Jul 21 '14 at 2:27 Abel 49.8k1919 gold badges126126 silver badges207207 bronze badges add a comment 5

How can I check if a value is null or empty with XSL?

For example, if categoryName is empty?

This is probably the simplest XPath expression (the one in accepted answer provides a test for the opposite, and would be longer, if negated):

not(string(categoryName))

Explanation:

The argument to the not() function above is false() exactly when there is no categoryName child ("null") of the context item, or the (single such) categoryName child has string value -- the empty string.

I'm using a when choosing construct.

For example:

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

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

Here is a complete example:

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

When this transformation is applied on the following XML document:

<categoryName>X</categoryName>

the wanted, correct result is produced:

X

When applied on this XML document:

<categoryName></categoryName>

or on this:

<categoryName/>

or on this

<somethingElse>Y</somethingElse>

the correct result is produced:

Other

Similarly, use this XSLT 1.0 transformation:

<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 note: No conditionals are used at all. Learn more about the importance of avoiding conditional constructs in this nice Pluralsight course:

"Tactical Design Patterns in .NET: Control Flow"

shareimprove this answer edited Jan 21 '16 at 3:02     answered Jan 1 '16 at 1:16 Dimitre Novatchev 221k2626 gold badges262262 silver badges384384 bronze badges add a comment 4

If there is a possibility that the element does not exist in the XML I would test both that the element is present and that the string-length is greater than 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>
shareimprove this answer answered Jun 14 '13 at 15:47 Marie Taylor 4111 bronze badge add a comment 3

If a node has no value available in the input xml like below xpath,

<node>
    <ErrorCode/>
</node>

string() function converts into empty value. So this works fine:

string(/Node/ErrorCode) =''
shareimprove this answer answered Apr 23 '15 at 9:35 Sanjeev Singh 3,53022 gold badges2626 silver badges3838 bronze badges add a comment 2

Something like this works for me:

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

Or the other way around:

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

Note: If you don't check null values or handle null values, IE7 returns -2147483648 instead of NaN.

shareimprove this answer edited Apr 23 '15 at 10:10 Sanjeev Singh 3,53022 gold badges2626 silver badges3838 bronze badges answered Aug 18 '11 at 10:12 HSol 2111 bronze badge add a comment 1

I actually found it better just testing for string length since many times the field is not null, just empty

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

shareimprove this answer answered Jun 23 '16 at 8:54 Pedro Pereira 44055 silver badges1212 bronze badges add a comment 0

By my experience the best way is:

<xsl:when test="not(string(categoryName))">
    <xsl:value-of select="other" />
</xsl:when>
<otherwise>
    <xsl:value-of select="categoryName" />
</otherwise>
shareimprove this answer edited Jul 29 '13 at 7:46     answered Jul 29 '13 at 7:40 dr_leevsey 15722 silver badges88 bronze badges add a comment 0

Use simple categoryName/text() Such test works fine on <categoryName/> and also <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>
shareimprove this answer answered Sep 10 '15 at 13:00 Jaroslav Kubacek 1,1791414 silver badges2323 bronze badges add a comment   Highly active question. Earn 10 reputation in order to answer this question. The reputation requirement helps protect this question from spam and non-answer activity.

Not the answer you're looking for? Browse other questions tagged     or ask your own question.

标签:sheet,XSLT,share,answer,post,null,data,Check,se
来源: https://www.cnblogs.com/ioriwellings/p/12420789.html