首页 文章

检查XSLT中的字符串是空还是空

提问于
浏览
301

如何使用XSL检查值是空还是空?

例如,如果 categoryName 为空?我在选择构造时使用的是 .

例如:

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

14 回答

  • 4

    前两个处理空值,第二个处理空字符串 .

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

    如果XML中可能存在该元素,我将测试该元素是否存在以及字符串长度是否大于零:

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

    我知道这个问题很老,但在所有答案之间,我想念一个在XSLT开发中这个用例的常用方法 .

    我想象OP中丢失的代码看起来像这样:

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

    输入看起来像这样:

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

    即,我假设可以有零,空,单个或多个 categoryName 元素 . 使用 xsl:choose 样式的构造来处理所有这些情况,或者换言之,强制性地,很快就会变得混乱(如果元素可以处于不同的级别,则更是如此!) . XSLT中的典型编程习惯是使用模板(因此是XSLT中的T),这是声明性编程,而不是必要的(您不告诉处理器该做什么,只要满足某些条件就告诉您想要输出什么) . 对于此用例,可能类似于以下内容:

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

    这适用于(使用任何XSLT版本),因为上面的第一个具有更高的优先级(它有一个谓词) . "fall-through"匹配模板(第二个)捕获任何无效的模板 . 然后第三个以正确的方式输出 categoryName 值 .

    请注意,在这种情况下,不需要特别匹配 categoriescategory ,因为处理器将自动处理所有子项,除非我们另外说明(在此示例中,第二个和第三个模板不会进一步处理子项,因为有其中没有 xsl:apply-templates ) .

    这种方法比命令式方法更容易扩展,因为它自动处理多个类别,并且可以通过添加另一个匹配模板来扩展其他元素或异常 . Programming without if-branches .

    注意:XML中没有 null 这样的东西 . 有xsi:nil,但很少使用,特别是在没有某种模式的无类型场景中很少使用 .

  • 0

    我实际上发现它只是测试字符串长度更好,因为很多时候字段不是空的,只是空的

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

  • 4
    test="categoryName != ''"
    

    Edit :在我看来,这涵盖了最有可能的解释"[not] null or empty",这是从问题推断出来的,包括它的伪代码和我自己早期使用XSLT的经验 . 即,"What is the equivalent of the following Java?":

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

    有关更多详细信息,例如,明确标识null与空,请参阅johnvey's answer below和/或the XSLT 'fiddle' I 've adapted from that answer, which includes the option in Michael Kay'的注释以及第六种可能的解释 .

  • 0

    根据我的经验,最好的方法是:

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

    如果节点在输入xml中没有可用值,如xpath下面,

    <node>
        <ErrorCode/>
    </node>
    

    string()函数转换为空值 . 所以这很好用:

    string(/Node/ErrorCode) =''
    
  • 2

    在某些情况下,您可能想知道值何时特别为null,这在使用从.NET对象序列化的XML时尤为必要 . 虽然接受的答案适用于此,但当字符串为空或空时,它也会返回相同的结果,即'',因此您无法区分 .

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

    所以你可以简单地测试属性 .

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

    有时需要知道确切的状态,你不能简单地检查是否实例化了CategoryName,因为与Javascript不同

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

    对于null元素将返回true .

  • 2

    如何使用XSL检查值是空还是空?例如,如果categoryName为空?

    This is probably the simplest XPath expression (接受答案中的那个提供相反的测试,如果否定则会更长):

    not(string(categoryName))
    

    Explanation

    上面的 not() 函数的参数是 false() ,正好没有上下文项的 categoryName 子("null"),或者(单个) categoryName 子具有字符串值 - 空字符串 .

    我在选择构造时使用的是 . 例如:<xsl:choose>
    <xsl:when test =“categoryName!= null”>
    <xsl:value-of select =“categoryName”/>
    </ XSL:当>
    的<xsl:否则>
    <xsl:value-of select =“other”/>
    </ XSL:否则>
    </ XSL:选择>

    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>
    

    或者:

    <categoryName/>
    

    或者就此而言

    <somethingElse>Y</somethingElse>
    

    the correct result is produced

    Other
    

    同样,使用此 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>
    

    Do note :根本没有使用条件 . 在这个精彩的Pluralsight课程中,详细了解避免条件结构的重要性:

    "Tactical Design Patterns in .NET: Control Flow"

  • 256

    使用简单的categoryName / text()这样的测试在 <categoryName/><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>
    
  • 19

    来自Empty Element

    测试某个节点的值是否为空

    这取决于你的意思是空的 .

    • 不包含子节点: not(node())

    • 不包含任何文字内容: not(string(.))

    • 不包含空格以外的文字: not(normalize-space(.))

    • 除评论外不包含任何内容: not(node()[not(self::comment())])

  • 304

    关于什么?

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

    这样的东西适合我:

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

    或者反过来说:

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

    注意:如果不检查空值或处理空值,IE7将返回-2147483648而不是NaN .

  • 0

    没有任何其他信息,我将假设以下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>
    

    示例用例如下所示:

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

相关问题