这是我在生成 XSL-FO 的更复杂的 XSLT 1.0 样式表中遇到的匹配问题的一个简单示例。
给定这个输入 XML,其中<Library>
可能包含零个或多个<Item>
节点,
<Library>
<Item type="magazine" title="Rum"/>
<Item type="book" title="Foo" author="Bar"/>
<Item type="book" title="Fib" author="Fub"/>
<Item type="magazine" title="Baz"/>
</Library>
而这个 XSLT:
<xsl:template match="Library">
<xsl:apply-templates select="Item[@type='Magazine']/>
<!-- How to call "NoMagazines" from here? -->
<xsl:apply-templates select="Item[@type='Book']/>
<!-- How to call "NoBooks" from here? -->
</xsl:template>
<xsl:template match="Item[@type='book']">
<!-- do something with books -->
</xsl:template>
<xsl:template match="Item[@type='magazine']">
<!-- do something with magazines -->
</xsl:template>
<!-- how to call this template? -->
<xsl:template name="NoBooks">
Sorry, No Books!
</xsl:template>
<!-- how to call this template? -->
<xsl:template name="NoMagazines">
Sorry, No Magazines!
</xsl:template>
我想制作替代品“对不起,不[无论如何]!” Library
当没有Item
类型 [whatever] 的节点时来自模板的消息。
到目前为止,我所做的唯一(丑陋)解决方案是按类型选择子节点到变量中,测试变量,然后如果变量包含节点,则应用模板,或者调用适当的“不匹配”命名模板,如果变量为空(我假设 test="$foo" 如果没有选择节点,将返回 false,我还没有尝试过):
<xsl:template match="Library">
<xsl:variable name="books" select="Items[@type='book']"/>
<xsl:choose>
<xsl:when test="$books">
<xsl:apply-templates select="$books"/>
</xsl:when>
<xsl:otherwise>
<xsl:call-template name="NoBooks"/>
</xsl:otherwise>
</xsl:choose>
<xsl:variable name="magazines" select="Items[@type='magazine']"/>
<xsl:choose>
<xsl:when test="$magazines">
<xsl:apply-templates select="$magazines"/>
</xsl:when>
<xsl:otherwise>
<xsl:call-template name="NoMagazines"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
我认为这一定是一种 XSLT 设计模式(在 GoF 意义上),但我在网上找不到任何示例。非常欢迎任何建议!