这是一种三维的例子,它涉及一个比较复杂的XSLT 1.0sheet,产生XSL-FO。
鉴于该投入XML,其中<Library>
可能含有零或以上<Item>
nodes,
<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>
而这一特别协定:
<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>
I want to produce the alternative Sorry, No [whatever]! message from the Library
template when there are no Item
nodes of the type [whatever].
So far, the only (ugly) solution I ve made is to select the child nodes by type into variables, test the variable, then either apply-templates if the variable contains nodes, or call the appropriate no match named template if the variable is empty (I m assuming test="$foo" will return false if no nodes are selected, I haven t tried it yet):
<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>
我认为,这必须是异常低价竞标的设计模式(从GoF的角度来看),但我无法在网上找到任何例子。 任何建议都受到热烈欢迎!