检查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”>