XSLT:如果存在标签,则应用模板;如果不存在,则选择静态值。

13

我对XSLT不太熟悉,请见谅...

基于此,我想要做的是检查XML中是否存在特定标签。如果存在,我想应用一个模板。如果不存在,则希望添加它(作为空值)。基本上总是强制它出现在最终输出中。我该如何实现这个功能?

我有类似以下的内容...

<xsl:choose>
    <xsl:when test="@href">
        <xsl:apply-templates select="country" />
    </xsl:when>
    <xsl:otherwise>
    </xsl:otherwise>
</xsl:choose>

我认为代码的前面部分有错误。需要在 otherwise 标签中添加一些内容,而且我认为我的 when 部分也有问题。

<xsl:template match="country">
    <xsl:if test=". != '' or count(./@*) != 0">
        <xsl:copy-of select="."/>
    </xsl:if>
</xsl:template>

有人可以帮忙吗?先谢谢了。

编辑:

最终我需要至少一个<country />标签出现在XML中。但是可能根本就不存在这个标签。如果它不存在,我必须加入它。一个好的例子是:<country>US</country>


考虑发布两个输入样本(一个包含数据,另一个不包含数据),然后展示我们想要创建的输出。然后我们可以帮助您使用适当的XSLT。恐怕您当前的描述“检查某个标记”不是很精确,很难确定<xsl:when test="@href">是否符合您的要求。这将检查上下文节点是否具有href属性,而检查“标记”似乎是要检查某些元素节点。在您的otherwise中,您可能只需要放置一个<country>foo</country>结果元素。 - Martin Honnen
'<xsl:when test="@href">' 是错误的,我认为。 - Issa Fram
1
好问题,+1。请看我的答案,比当前被接受的答案更短更简单。在我的解决方案中绝对没有XSLT条件指令! - Dimitre Novatchev
3个回答

12
在父元素的模板中,国家元素应该被使用,例如:
<xsl:template match="foo">
  <xsl:if test="not(country)">
    <country>US</country>
  </xsl:if>
  <xsl:apply-templates/>
</xsl:template>

不要使用foo,而是使用父元素的名称。当然,您也可以执行其他操作,例如复制元素,但我专注于if检查。在我看来,您实际上不需要xsl:choose/when/otherwise,因为xsl:if应该足以满足需求,因为apply-templates不会对不存在的子元素执行任何操作。


我做了非常类似的事情...所以我猜你得到了正确的答案。时间对于这个很重要,所以我一直调整直到正确为止。但还是谢谢。 - Issa Fram
如果我想要查看某个变量是否不存在或为空,该怎么办? - SearchForKnowledge
1
@SearchForKnowledge,考虑提出一个新的、独立的问题,并附上您需要的XML输入和结果的必要细节。 - Martin Honnen

12

更简单的方法:

<xsl:template match="foo[not(country)]">
        <country>US</country>
    <xsl:apply-templates/>
</xsl:template>

请注意:

不会使用任何XSLT条件指令(例如<xsl:if>),也不需要它们。

很多时候,存在<xsl:if><xsl:choose>表明代码可以进行重构和显著改进,其中一项是消除条件指令。


但是如果您需要提供另一个默认元素呢?例如,<city>。 - JRQ
@JRQ,在这种情况下没有提供特定的源XML文档,因此只能猜测所需的模式。例如:US Washington或者它可能是(可能性是无限的): Washington - Dimitre Novatchev
我可以理解您的想法。但是,一个更通用的解决方案将比仅适用于测试数量少于 1 的解决方案更为优秀。 - JRQ
@JRQ,同意。这就是为什么任何人都可以提出一个新问题,说明他们感兴趣的更具体的情况。 - Dimitre Novatchev

6

您甚至不需要任何形式的条件处理。这个样式表:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="node()|@*">
        <xsl:copy>
            <xsl:apply-templates select="node()|@*"/>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="item[not(country)]">
        <xsl:copy>
            <xsl:apply-templates select="node()|@*"/>
            <country>Lilliput</country>
        </xsl:copy>
    </xsl:template>
</xsl:stylesheet>

使用这个输入:

<root>
    <item>
        <country>Brobdingnag</country>
    </item>
    <item>
        <test/>
    </item>
</root>

输出:

<root>
    <item>
        <country>Brobdingnag</country>
    </item>
    <item>
        <test></test>
        <country>Lilliput</country>
    </item>
</root>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接