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

发布于 2024-07-19 03:31:27 字数 467 浏览 9 评论 0原文

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

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>

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(14

油饼 2024-07-26 03:31:27
test="categoryName != ''"

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

// Equivalent Java, NOT XSLT
!(categoryName == null || categoryName.equals(""))

有关更多详细信息,例如,明确识别 null 与空,请参阅下面的 johnvey 的回答 和/或 XSLT 'fiddle' 我改编自该答案,其中包括迈克尔·凯评论中的选项以及第六种可能的解释。

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

// Equivalent Java, NOT XSLT
!(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.

月亮坠入山谷 2024-07-26 03:31:27

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

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>
薄情伤 2024-07-26 03:31:27

来自空元素

测试如果某个节点的值为空

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

  • 不包含子节点: not(node())
  • 不包含文本内容: not(string(.))
  • 不包含除空格以外的任何文本: not(normalize -space(.))
  • 除注释外不包含任何内容:not(node()[not(self::comment())])

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())])
油饼 2024-07-26 03:31:27

关于什么?

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

What about?

test="not(normalize-space(categoryName)='')"
柒七 2024-07-26 03:31:27

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

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

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>
ま柒月 2024-07-26 03:31:27

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

例如,如果categoryName为空?

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

not(string(categoryName))

解释

<的参数当上下文项没有 categoryName 子项(“null”)或(单个这样)categoryName 子项具有字符串值——空字符串。

我在选择构造时使用结构。

例如:

; 
       
           
       
       
           
       
   
  

在 XSLT 2.0 中使用

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

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

<categoryName>X</categoryName>

想要的,会产生正确的结果

X

当应用于此 XML 文档时

<categoryName></categoryName>

或在此:

<categoryName/>

或在此

<somethingElse>Y</somethingElse>

产生正确的结果

Other

类似地,使用此 < strong>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>

请注意:根本不使用任何条件。 在这个精彩的 Pluralsight 课程中详细了解避免条件构造的重要性:

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

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"

若水微香 2024-07-26 03:31:27

在某些情况下,您可能想知道该值何时具体为 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。

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.

做个ˇ局外人 2024-07-26 03:31:27

我知道这个问题已经很老了,但在所有答案中,我错过了 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 版本),因为上面的第一个具有更高的优先级(它有一个谓词)。 第二个“失败”匹配模板捕获任何无效的内容。 然后,第三个负责以正确的方式输出 categoryName 值。

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

这种方法比命令式方法更容易扩展,因为它自动处理多个类别,并且只需添加另一个匹配模板就可以针对其他元素或异常进行扩展。 没有 if 分支的编程

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

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.

悲喜皆因你 2024-07-26 03:31:27

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

<xsl:choose>
    <xsl:when test="categoryName and string-length(categoryName) > 0">
        <xsl:value-of select="categoryName " />
    </xsl:when>
    <xsl:otherwise>
        <xsl:value-of select="other" />
    </xsl:otherwise>
</xsl:choose>

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) > 0">
        <xsl:value-of select="categoryName " />
    </xsl:when>
    <xsl:otherwise>
        <xsl:value-of select="other" />
    </xsl:otherwise>
</xsl:choose>
还如梦归 2024-07-26 03:31:27

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

<node>
    <ErrorCode/>
</node>

string() 函数将转换为空值。 所以这工作正常:

string(/Node/ErrorCode) =''

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) =''
后eg是否自 2024-07-26 03:31:27

像这样的东西对我有用:

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

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.

凑诗 2024-07-26 03:31:27

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

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

韶华倾负 2024-07-26 03:31:27

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

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

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>
提笔书几行 2024-07-26 03:31:27

使用简单的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>

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>
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文