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

rak*_*los 318 xslt null xslt-2.0 xslt-1.0

如何使用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>
Run Code Online (Sandbox Code Playgroud)

ste*_*r25 317

test="categoryName != ''"
Run Code Online (Sandbox Code Playgroud)

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

!(categoryName == null || categoryName.equals(""))
Run Code Online (Sandbox Code Playgroud)

有关更多详细信息,例如,清楚地标识null与空,请参阅下面的johnvey答案和/或XSLT'小提琴'我改编自该答案,其中包括Michael Kay评论中的选项以及第六种可能的解释.

  • 此测试的详细语义为:如果至少有一个categoryName元素,其字符串值为空字符串,则返回true. (14认同)
  • @jelovirt你的意思是说至少有一个categoryName不是空字符串吗?(我是一个xsl新手,请原谅我的问题任何潜在的愚蠢.) (14认同)
  • 这个答案虽然被接受并高度投票,但也具有误导性.这真的取决于你的意思是"空或空".如果你想要一个如果categoryName不存在或者带有零长度值的测试成功,你应该使用`test ="not(categoryName ='')"`.如果categoryName元素不存在,则提供的答案将返回false,这在我对问题的解释中使其成为错误的答案. (10认同)
  • @MichaelKay:我已经更新了答案以提供更多详细信息。感谢您的评论和Saxon XSLT处理器! (2认同)

joh*_*vey 266

没有任何其他信息,我将假设以下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>
Run Code Online (Sandbox Code Playgroud)

示例用例如下所示:

<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>
Run Code Online (Sandbox Code Playgroud)

  • 我专门为这个答案主演了这个问题,虽然这个问题已经很老了,但这个问题似乎更值得选择答案 (4认同)
  • 感谢您提供了多个示例来说明每个表达式的结果. (2认同)

Chr*_*ett 66

空元素:

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

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

  • 不包含子节点: not(node())
  • 不包含文字内容: not(string(.))
  • 除了空格之外不包含任何文本: not(normalize-space(.))
  • 除评论外不包含任何内容: not(node()[not(self::comment())])

  • +1.一些笔记.第一个要点还测试文本内容,它也是一个节点.第二个要点测试任何深度的任何文本节点,如果你想知道当前节点是否包含文本,但是可以包含其他节点,你可以使用`not(text())`.你的第二个子弹的替代品也是'not(.// text())`.正如你的最后一颗子弹所示:有许多方法可以考虑"虚无";). (2认同)

hel*_*cim 22

关于什么?

test="not(normalize-space(categoryName)='')"
Run Code Online (Sandbox Code Playgroud)

  • 这很好用。即使在 `&lt;categoryName&gt; &lt;!-- some comment --&gt; &lt;/categoryName&gt;` 中存在注释并且没有有意义的文本,这仍然会评估为 `true` (2认同)

Ale*_*vac 9

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

<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>
Run Code Online (Sandbox Code Playgroud)


Dim*_*hev 7

如何使用 XSL 检查值是否为 null 或为空?

例如,如果categoryName是空的?

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

not(string(categoryName))
Run Code Online (Sandbox Code Playgroud)

说明

not()上面函数的参数false()恰好是categoryName上下文项没有子项(“null”),或者(单个这样的)categoryName子项具有字符串值——空字符串。

在选择构造使用 a 。

例如:

<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>
Run Code Online (Sandbox Code Playgroud)

在 XSLT 2.0 中使用

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

这是一个完整的示例

<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>
Run Code Online (Sandbox Code Playgroud)

当此转换应用于以下 XML 文档时:

<categoryName>X</categoryName>
Run Code Online (Sandbox Code Playgroud)

产生了想要的、正确的结果

X
Run Code Online (Sandbox Code Playgroud)

应用于此 XML 文档时

<categoryName></categoryName>
Run Code Online (Sandbox Code Playgroud)

或在此:

<categoryName/>
Run Code Online (Sandbox Code Playgroud)

或在此

<somethingElse>Y</somethingElse>
Run Code Online (Sandbox Code Playgroud)

产生正确的结果

Other
Run Code Online (Sandbox Code Playgroud)

同样,使用这个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>
Run Code Online (Sandbox Code Playgroud)

请注意:根本不使用条件。在这个不错的 Pluralsight 课程中了解有关避免条件结构的重要性的更多信息:

.NET 中的战术设计模式:控制流


小智 6

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

<group>
    <item>
        <id>item 1</id>
        <CategoryName xsi:nil="true" />
    </item>
</group>
Run Code Online (Sandbox Code Playgroud)

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

<xsl:if test="CategoryName/@xsi:nil='true'">
   Hello World.
</xsl:if>
Run Code Online (Sandbox Code Playgroud)

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

<xsl:if test="CategoryName">
   Hello World.
</xsl:if>
Run Code Online (Sandbox Code Playgroud)

对于null元素将返回true.


小智 5

如果 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>
Run Code Online (Sandbox Code Playgroud)

  • 空节点集的字符串值(当前上下文中没有“categoryName”子元素时 XPath 表达式“categoryName”给出的值)被定义为空字符串,因此这是多余的 -“string-”如果没有“categoryName”元素,则 length(categoryName)` 为零。 (3认同)

Abe*_*bel 5

我知道这个问题很老,但是在所有答案之间,我都错过了一个在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>
Run Code Online (Sandbox Code Playgroud)

输入看起来像这样:

<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>
Run Code Online (Sandbox Code Playgroud)

即,我假设可以有零,空,单个或多个categoryName元素。使用xsl:choose-style构造来处理所有这些情况,换句话说,势在必行,很快就会变得混乱(如果元素可以处于不同的级别,则更加麻烦!)。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>
Run Code Online (Sandbox Code Playgroud)

这适用于任何XSLT版本,因为上面的第一个优先级更高(具有谓词)。第二个匹配模板是“穿透”匹配模板,可以捕获所有无效模板。然后,第三个负责categoryName以适当的方式输出值。

请注意,在这种情况下,无需专门匹配categoriescategory,因为处理器将自动处理所有子项,除非我们另行通知(在此示例中,第二个和第三个模板不会进一步处理子项,因为没有xsl:apply-templatesin他们)。

这种方法比命令式方法更容易扩展,因为它可以自动处理多个类别,并且可以通过添加其他匹配模板将其扩展为其他元素或例外。没有if分支的编程

注意:nullXML中没有这样的东西。有xsi:nil,但是很少使用,尤其是在没有某种模式的无类型脚本中尤其如此。