如何删除模板中的代码重复

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>