如何删除模板中的代码重复
How to remove code duplication in template
我有以下 XSLT 模板
<xsl:template match="body/table/rows">
<fo:table-row font-weight="bold">
<fo:table-cell>
<fo:block>
<xsl:value-of select="date" />
</fo:block>
</fo:table-cell>
..............
</fo:table-row>
</xsl:template>
<xsl:template match="body/table/result">
<fo:table-row>
<fo:table-cell>
<fo:block>
<xsl:value-of select="date" />
</fo:block>
</fo:table-cell>
..............
</fo:table-row>
</xsl:template>
模板的区别在于元素 <fo:table-row>
有 font-weight="bold"
而另一个没有,但是两个模板的内容都是由 <fo:table-cell
是一样的,显然这是代码重复。有没有办法删除此代码重复?
使用模式:
<xsl:template match="*" mode="cell">
<fo:table-cell>
<fo:block>
<xsl:value-of select="date" />
</fo:block>
</fo:table-cell>
</xsl:template>
和 apply-templates 你有 fo:table-cell
元素,即使用 <xsl:apply-templates select="." mode="cell"/>
.
您还可以考虑对模板进行参数化,并将 fo:table-row
与字体粗细作为参数。
试试这个:
<xsl:template match="body/table/rows | body/table/result">
<fo:table-row>
<xsl:apply-templates select="." mode="font-weight"/>
<fo:table-cell>
<fo:block>
<xsl:value-of select="date" />
</fo:block>
</fo:table-cell>
..............
</fo:table-row>
</xsl:template>
<xsl:template match="body/table/rows" mode="font-weight">
<xsl:attribute name="font-weight">bold</xsl:attribute>
</xsl:template>
<xsl:template match="*" mode="font-weight"/>
恕我直言,在您的情况下,最简单的解决方案是有条件地添加属性:
<xsl:template match="rows | result">
<fo:table-row>
<xsl:if test="self::rows">
<xsl:attribute name="font-weight">bold</xsl:attribute>
</xsl:if>
<fo:table-cell>
<fo:block>
<xsl:value-of select="date" />
</fo:block>
</fo:table-cell>
<!-- .... -->
</fo:table-row>
</xsl:template>
更通用的解决方案是将通用代码放在 named 模板中,然后 从两个特定模板中调用 该模板,或者 - 在XSLT 2.0 及更高版本 - 使用 xsl:next-match
指令。
未测试,因为未提供输入示例。
假设您至少使用 XSLT 2.0...
<xsl:template match="body/table/result" name="row">
<xsl:param name="atts" select="()" as="attribute()*" />
<fo:table-row>
<xsl:sequence select="$atts" />
<fo:table-cell>
<fo:block>
<xsl:value-of select="date" />
</fo:block>
</fo:table-cell>
..............
</fo:table-row>
</xsl:template>
<!-- A higher-priority template or a template in an importing
stylesheet can use <xsl:next-match> and provide overriding
attributes. -->
<xsl:template match="body/table/rows">
<xsl:param name="atts" select="()" as="attribute()*" />
<xsl:call-template name="row">
<xsl:with-param name="atts" as="attribute()*">
<xsl:attribute name="font-weight">bold</xsl:attribute>
<xsl:sequence select="$atts" />
</xsl:call-template>
</xsl:template>
我有以下 XSLT 模板
<xsl:template match="body/table/rows">
<fo:table-row font-weight="bold">
<fo:table-cell>
<fo:block>
<xsl:value-of select="date" />
</fo:block>
</fo:table-cell>
..............
</fo:table-row>
</xsl:template>
<xsl:template match="body/table/result">
<fo:table-row>
<fo:table-cell>
<fo:block>
<xsl:value-of select="date" />
</fo:block>
</fo:table-cell>
..............
</fo:table-row>
</xsl:template>
模板的区别在于元素 <fo:table-row>
有 font-weight="bold"
而另一个没有,但是两个模板的内容都是由 <fo:table-cell
是一样的,显然这是代码重复。有没有办法删除此代码重复?
使用模式:
<xsl:template match="*" mode="cell">
<fo:table-cell>
<fo:block>
<xsl:value-of select="date" />
</fo:block>
</fo:table-cell>
</xsl:template>
和 apply-templates 你有 fo:table-cell
元素,即使用 <xsl:apply-templates select="." mode="cell"/>
.
您还可以考虑对模板进行参数化,并将 fo:table-row
与字体粗细作为参数。
试试这个:
<xsl:template match="body/table/rows | body/table/result">
<fo:table-row>
<xsl:apply-templates select="." mode="font-weight"/>
<fo:table-cell>
<fo:block>
<xsl:value-of select="date" />
</fo:block>
</fo:table-cell>
..............
</fo:table-row>
</xsl:template>
<xsl:template match="body/table/rows" mode="font-weight">
<xsl:attribute name="font-weight">bold</xsl:attribute>
</xsl:template>
<xsl:template match="*" mode="font-weight"/>
恕我直言,在您的情况下,最简单的解决方案是有条件地添加属性:
<xsl:template match="rows | result">
<fo:table-row>
<xsl:if test="self::rows">
<xsl:attribute name="font-weight">bold</xsl:attribute>
</xsl:if>
<fo:table-cell>
<fo:block>
<xsl:value-of select="date" />
</fo:block>
</fo:table-cell>
<!-- .... -->
</fo:table-row>
</xsl:template>
更通用的解决方案是将通用代码放在 named 模板中,然后 从两个特定模板中调用 该模板,或者 - 在XSLT 2.0 及更高版本 - 使用 xsl:next-match
指令。
未测试,因为未提供输入示例。
假设您至少使用 XSLT 2.0...
<xsl:template match="body/table/result" name="row">
<xsl:param name="atts" select="()" as="attribute()*" />
<fo:table-row>
<xsl:sequence select="$atts" />
<fo:table-cell>
<fo:block>
<xsl:value-of select="date" />
</fo:block>
</fo:table-cell>
..............
</fo:table-row>
</xsl:template>
<!-- A higher-priority template or a template in an importing
stylesheet can use <xsl:next-match> and provide overriding
attributes. -->
<xsl:template match="body/table/rows">
<xsl:param name="atts" select="()" as="attribute()*" />
<xsl:call-template name="row">
<xsl:with-param name="atts" as="attribute()*">
<xsl:attribute name="font-weight">bold</xsl:attribute>
<xsl:sequence select="$atts" />
</xsl:call-template>
</xsl:template>