检查XSLT中的string是否为空或空

我怎样才能检查一个值是否为空或空的XSL ?

例如,如果categoryName是空的? 我正在使用select结构。

例如:

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

 test="categoryName != ''" 

编辑 :这涵盖了最可能的解释,在我看来,从这个问题推断出的“[不]空或空”,包括它的伪代码和我自己早期的XSLT经验。 也就是说,“以下Java的等价物是什么?”:

!(categoryName == null || categoryName.equals(“”))。

有关更多详细信息,例如,清楚地标识空对空 ,请参阅下面的johnvey的答案和/或我已经从该答案改编的XSLT“小提琴” ,其中包括迈克尔凯评论的选项以及第六种可能的解释。

在没有任何其他信息的情况下,我将假定以下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> 

空的元素

testing某个节点的值是否为空

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

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

关于什么?

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

前两个处理空值,后两个处理空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> 

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

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

所以你可以简单地testing属性。

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

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

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

将为null元素返回true。

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

我在想像OP中缺less的代码如下所示:

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

而且input看起来像这样:

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

这可以工作(使用任何XSLT版本),因为上面的第一个具有更高的优先级(它有一个谓词)。 第二个匹配模板“fall-through”捕获任何无效的东西。 然后第三个负责以正确的方式输出categoryName值。

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

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

注意:XML中不存在null 。 有xsi:nil ,但很less使用,特别是在没有某种模式的无types的情况下很less使用。

如果在XML中不存在该元素的可能性,我会testing该元素是否存在,并且string长度是否大于零:

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

如果一个节点在inputxml中没有像xpath一样的可用值,

 <node> <ErrorCode/> </node> 

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

 string(/Node/ErrorCode) ='' 

像这样的东西适合我:

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

我怎样才能检查一个值是否为空或空的XSL?

例如,如果categoryName是空的?

这可能是最简单的XPathexpression式 (被接受的答案提供了相反的testing,如果否定,则会更长):

 not(string(categoryName)) 

说明

上面的not()函数的参数在上下文项的没有categoryName子(“null”)的情况下是false() ,或者(single这样的) categoryName子有string值 – 空string。

我正在使用select结构。

例如:

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

在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 

同样,使用这个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中的战术devise模式:控制stream

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

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

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

实际上,我发现它只是testingstring长度,因为很多时候字段不是空的,只是空的

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