检查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值。 
 请注意,在这种情况下,没有必要特别匹配categories或category ,因为处理器会自动处理所有的孩子,除非我们另有说明(在这个例子中,第二和第三个模板不会进一步处理孩子,因为有没有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) > 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”>