在我的xsl中,已经为para,graphic等元素定义了模板。例如:
<xsl:template match="para">
<fo:block>
<xsl:apply-templates />
</fo:block>
</xsl:template>
但是我希望在特定属性值的情况下在最里面添加额外的节点。例如,如果元素的属性值为changeStatus = new / changed,我需要添加&#39; fo:change-bar-begin&#39;其他节点内的元素。示例xml:
<para changeStatus="new">
This is a paragraph that has change bars applied to the whole paragraph. </para>
输出应该是(这里:块节点来自xsl中的其他模板):
<fo:block>
<fo:change-bar-begin change-bar-style="solid"/>
This is a paragraph that has change bars applied to the whole paragraph.
<fo:change-bar-end/>
</fo:block>
我正在使用此代码,但在某些情况下,它是在外层添加节点,而在其他情况下,它正在删除在其他模板中定义的节点(例如:fo:block)。
<xsl:template match="*[@changeStatus='new' or @changeStatus='changed']">
<fo:change-bar-begin change-bar-style="solid"/>
<xsl:apply-templates select="node() | @*" />
<fo:change-bar-end/>
</xsl:template>
这里,para只是一个例子,我需要这个代码来处理许多元素,所以使用call-template不是一个选项。 请建议最好的方法。
答案 0 :(得分:2)
每次选择一个节点进行转换时,只有一个模板与其匹配并应用,除非所选模板可以指示其他模板应用于同一节点。因此,如果添加一个匹配已经具有匹配模板的节点的模板,那么您将获得一个模板或另一个模板的效果,而不是两者的组合。
现在,如果你想把你的change-bar
放在现有模板生成的最外层元素那么这将是一回事,但是放change-bar
在内部,他们需要修改或克隆需要这种处理的所有现有模板。我强烈推荐“修改”替代方案,因为维护它会更容易。
例如,将您的模板与para
元素匹配。您可以像这样修改它:
<xsl:template match="para">
<fo:block>
<xsl:apply-templates select="." mode="cb-begin-choice"/>
<xsl:apply-templates />
<xsl:apply-templates select="." mode="cb-end-choice"/>
</fo:block>
</xsl:template>
对于所有模板,您会支持这样的事情:
<xsl:template match="*" mode="cb-begin-choice">
<xsl:if test="@changeStatus='new' or @changeStatus='changed'">
<fo:change-bar-begin change-bar-style="solid"/>
</xsl:if>
</xsl:template>
<xsl:template match="*" mode="cb-end-choice">
<xsl:if test="@changeStatus='new' or @changeStatus='changed'">
<fo:change-bar-end/>
</xsl:if>
</xsl:template>
将更改栏详细信息拉出到这两个附加模板可以更轻松地进行这些更改,并使修改后的模板更加清晰。它还为您提供了一个控制更改栏详细信息的位置,因此,如果您想要更改它们,则可以只在这两个模板中执行此操作。
如果您愿意,可以在命名模板和xsl:call-template
之上实现相同的功能,而不是模式和xsl:apply-templates
。