Check if a string is null or empty in XSLT

前端 未结 14 993
梦毁少年i
梦毁少年i 2020-11-27 09:12

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

相关标签:
14条回答
  • 2020-11-27 09:37

    From Empty Element:

    To test if the value of a certain node is empty

    It depends on what you mean by empty.

    • Contains no child nodes: not(node())
    • Contains no text content: not(string(.))
    • Contains no text other than whitespace: not(normalize-space(.))
    • Contains nothing except comments: not(node()[not(self::comment())])
    0 讨论(0)
  • 2020-11-27 09:37

    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.

    0 讨论(0)
  • 2020-11-27 09:39

    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>
    
    0 讨论(0)
  • 2020-11-27 09:42

    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>
    
    0 讨论(0)
  • 2020-11-27 09:44

    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.

    0 讨论(0)
  • 2020-11-27 09:44

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

    0 讨论(0)
提交回复
热议问题