我有一个类似以下的XML结构:
<Root>
<!-- ...other stuff -->
<Events>
<Event date="0000-00-00">Event Description etc...</Event>
<Event date="0000-00-00">Event Description etc...</Event>
<Event date="0000-00-00">Event Description etc...</Event>
</Events>
<!-- ...other stuff -->
</Root>
然后我在样式表中有XSLT,如下所示:
<xsl:variable name="Events" select="/Root/Events/Event" />
<xsl:template match="/">
<!-- Stuff -->
<xsl:apply-templates select="$Events" />
<!-- Stuff -->
</xsl:template>
<xsl:template match="Event">
<!-- Regular Event Template Transformation here -->
</xsl:template>
<!-- ERROR HAPPENS HERE -->
<xsl:template match="not(node())">
<p class="message">There are currently no upcoming events</p>
</xsl:template>
我想要做的是有两个模板,一个仅在没有事件时显示。我知道我可以使用带有<xsl:choose>
和<xsl:when>
测试的XSLT进行元素计数,并像过程语言一样调用正确的模板,但我正在尝试学习如何执行此操作用模板处理。
我得到的错误是: 表达式的预期结束,找到'('。not - &gt;(&lt; - node())
答案 0 :(得分:8)
not(node())
不是有效的XSLT模式,请尝试:
<xsl:template match="Event">
<!-- Regular Event Template Transformation here -->
</xsl:template>
<xsl:template match="Events[not(Event)]">
<p class="message">There are currently no upcoming events</p>
</xsl:template>
答案 1 :(得分:3)
这可能效果更好
<xsl:template match="*[not(node())]">
<!-- ... -->
答案 2 :(得分:2)
彻底阅读你的问题,我意识到我的最后解决方案无处可去。我的新答案如下:
由于您需要知道Events
内是否有任何元素,因此您需要更改/
匹配模板:
<xsl:template match="/">
<!-- Stuff -->
<xsl:apply-templates select="/Root/Events" />
<!-- Stuff -->
</xsl:template>
现在,该模板仅匹配填充Events
以及所需的Event
模板:
<xsl:template="Events[count(child::Event) > 0]">
<xsl:apply-template select='./Event'/>
</xsl:template>
<xsl:template="Event">
<!-- some stuff -->
</xsl:template>
现在匹配空Events
的模板:
<xsl:template="Events[count(child::Event) = 0]">
<p class="message">There are currently no upcoming events</p>
</xsl:template>
尝试:
<!-- This matches every node with an empty string repr. Maybe you want
to replace "self::*" to avoid attributes, etc." -->
<xsl:template match="*[string-length(self::*) = 0]">
</xsl:template>
详细说明:
如果我没记错的话,在XPath / XSL中'*'匹配任何类型的节点,即文本节点,元素节点,注释节点,属性节点等......所以在给定的上下文中*[string-length(self::*) = 0]
可能与属性匹配;例如,你可能在其他地方有一个select='@*'
。因此,此模板可以应用于属性和元素。
如果您确定它与任何属性都不匹配,您可以将其保留原样。但是,我喜欢我的代码表达了正确的想法。因此,如果此模板仅适用于Event元素,我会更改匹配项:
<xsl:template match="Event[string-length(self::*) = 0]">
</xsl:template>
在http://www.w3.org/TR/xslt处查看XSLT规范,似乎*仅匹配元素。但是,我会测试它。
答案 3 :(得分:1)
您的处理器抛出错误,因为您的匹配模式会产生布尔值,而不是节点。
尝试此转换(保留所需的变量):
<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="Events" select="/Root/Events/Event"/>
<xsl:template match="Root">
<xsl:apply-templates select="$Events
| Events[not(Event)]"/>
</xsl:template>
<xsl:template match="Event">
<p class="message">There is an event</p>
</xsl:template>
<xsl:template match="Events">
<p class="message">There are currently no upcoming events</p>
</xsl:template>
</xsl:stylesheet>
在您的输入上应用时,生成:
<p class="message">There is an event</p>
<p class="message">There is an event</p>
<p class="message">There is an event</p>
在没有事件的情况下应用于输入时,例如:
<Root>
<Events/>
</Root>
产生
<p class="message">There are currently no upcoming events</p>