检查XSLT中的字符串是否为null或空

检查XSLT中的字符串是否为null或空,xslt,null,xslt-1.0,xslt-2.0,Xslt,Null,Xslt 1.0,Xslt 2.0,如何检查值是否为null或空 例如,如果categoryName为空?我在选择构造时使用了 例如: <xsl:choose> <xsl:when test="categoryName !=null"> <xsl:value-of select="categoryName " /> </xsl:when> <xsl:otherwise> <xsl:value-of select

如何检查值是否为null或空

例如,如果
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>
<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>

编辑:在我看来,这涵盖了从问题中推断出的“[not]null或empty”最可能的解释,包括它的伪代码和我自己早期使用XSLT的经验。例如,“以下Java的等价物是什么?”:

有关更多详细信息,例如,明确识别空与空,请参阅和/或我根据该答案改编,其中包括Michael Kay评论中的选项以及第六种可能的解释。

来源:

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

这取决于你所说的空是什么意思

  • 不包含子节点:
    not(node())
  • 不包含文本内容:
    not(字符串()
  • 除空白外不包含任何文本:
    not(规范化空格()
  • 除注释外,不包含任何内容:
    not(node()[not(self::comment())])

    • 如果没有任何其他信息,我将假设以下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>
      
      
      项目1
      蓝色
      项目2
      项目3
      ...
      
      示例用例如下所示:

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

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

      <group>
          <item>
              <id>item 1</id>
              <CategoryName xsi:nil="true" />
          </item>
      </group>
      
      
      项目1
      
      因此,您可以简单地测试属性

      <xsl:if test="CategoryName/@xsi:nil='true'">
         Hello World.
      </xsl:if>
      
      
      你好,世界。
      
      有时需要知道确切的状态,而不能简单地检查CategoryName是否已实例化,因为与Javascript不同

      <xsl:if test="CategoryName">
         Hello World.
      </xsl:if>
      
      
      你好,世界。
      

      对于空元素,将返回true。

      类似的内容适用于我:

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

      如何

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

      前两个处理空值,后两个处理空字符串

      <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>
      
      
      用户名不为空
      用户名为空
      用户名是空字符串
      用户名不是空字符串
      
      如果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>
      
      
      
      根据我的经验,最好的方法是:

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

      我知道这个问题很老,但在所有答案中,我错过了一个XSLT开发中此用例的常用方法

      我在想象OP中缺失的代码是这样的:

      <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>
      
      
      
      输入看起来像这样:

      <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>
      
      这是可行的(适用于任何XSLT版本),因为上面的第一个版本具有更高的优先级(它有一个谓词)。第二个匹配模板“fall-through”捕获任何无效的内容。然后,第三个函数负责以适当的方式输出
      categoryName

      请注意,在这种情况下,不需要指定匹配
      类别
      类别
      ,因为处理器将自动处理所有子级,除非我们另有说明(在本例中,第二个和第三个模板不进一步处理子级,因为它们中没有
      xsl:apply模板

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


      注意:XML中没有
      null
      这样的东西。有,但很少使用,尤其是在没有某种模式的非类型化场景中。

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

      <node>
          <ErrorCode/>
      </node>
      

      使用simple categoryName/text()这样的测试在
      上都能正常工作

      <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>
      
      
      
      如何使用XSL检查值是否为null或空

      例如,如果
      categoryName
      为空

      这可能是最简单的XPath表达式(接受答案中的表达式提供了相反的测试,如果否定,则会更长):

      说明

      <xsl:copy-of select="concat(categoryName,  $vOther[not(string(current()/categoryName))])"/>
      
      <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>
      
      X
      
      <categoryName></categoryName>
      
      Other
      
      上面的
      not()
      函数的参数是
      false()
      ,正好当上下文项没有
      categoryName
      子项(“null”)时,或者(单个这样的)
      categoryName
      子项具有字符串值——空字符串

      <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>
      
      我在选择构造时使用了

      例如:

      <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>
      
      <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>
      
      应用于此XML文档时

      <xsl:copy-of select="concat(categoryName,  $vOther[not(string(current()/categoryName))])"/>
      
      <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>
      
      X
      
      <categoryName></categoryName>
      
      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>
      
      
      
      请注意:完全不使用条件。了解更多关于在本课程中避免条件构造的重要性:


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


      你可以扩展代码示例吗?根据你的用例,你可能不想使用<代码> XSL:当节点测试的< /代码>时,考虑<代码>…>代码>连同<代码>…>代码>。处理器将为Y做出正确的决定。