今天早上,我正在为 xhtml 标签实现 xsl-fo 格式。 通常,您希望引文为斜体:
<xsl:template match="cite">
<fo:inline font-style="italic"><xsl:apply-templates/></fo:inline>
</xsl:template>
当然,存在这种复杂性:如果周围的文本已经是斜体,那么为了对比的目的,您希望引文字体样式是正常的。 解决这个问题的第一个有点幼稚的尝试可以在Doug Tidwell的IBM教程(http://www.ibm.com/developerworks/library/x-xslfo2app/#cite)中找到:
<xsl:template match="cite">
<xsl:choose>
<xsl:when test="parent::i">
<fo:inline font-style="normal">
<xsl:apply-templates select="*|text()"/>
</fo:inline>
</xsl:when>
<xsl:otherwise>
<fo:inline font-style="italic">
<xsl:apply-templates select="*|text()"/>
</fo:inline>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
这是可以的,除了 xsl-fo 允许在任何块或内联标签中使用字体样式属性。 因此,想象一下,在稍微修改过的 html 风格中,font-style 属性可以出现在任何(xhtml strict)块或内联标签中,这些块或内联标签可以包含文本或包含文本的子项(除了出现在 xsl-fo 输出中)。 我试图解决的难题是,您如何确定任何特定的引文是否应该斜体化?
我解决问题的第一针:
<xsl:template match="cite">
<fo:inline>
<xsl:choose>
<xsl:when test="ancestor::i">
<xsl:variable name="font-style" select="'normal'"/>
</xsl:when>
<xsl:when test="parent::*[@font-style='italic']">
<xsl:variable name="font-style" select="'normal'"/>
</xsl:when>
<xsl:when test="parent::*[@font-style='normal']">
<xsl:variable name="font-style" select="'italic'"/>
</xsl:when>
<xsl:when test="ancestor::*[@font-style='italic']">
<xsl:variable name="font-style" select="'normal'"/>
</xsl:when>
<xsl:otherwise>
<xsl:variable name="font-style" select="'italic'"/>
</xsl:otherwise>
<xsl:attribute font-style=$font-style/>
<xsl:apply-templates/>
</fo:inline>
</xsl:template>
当然,很明显,这并非在所有情况下都有效:
<div font-style="italic">
<p font-style="normal">Old, but good science fiction, such as
<b><cite>Stephenson, Neil "Snowcrash"</cite></b>
more text....
</p></div>
上面的模板会将引文的字体样式设置为正常,因为此条件将是第一个满足的条件:
<xsl:when test="ancestor::*[@font-style='italic']">
我想过类似的事情
test="count(ancestor::*[@font-style='italic']) - count(ancestor::*[@font-style='normal') mod 2 = 0"
但这也不起作用,因为标签的顺序很重要;也就是说,做这样的事情是完全合法的:
<div font-style="italic> ... <p font-style="italic"> ...</p></div>
我知道我将如何使用过程语言来做到这一点:通过祖先列表向后计数,递增/递减"斜体"计数变量,但我想不出在 XSL 中执行此操作的任何方法,因为变量是不可变的。
听起来你真的只需要知道包含@font-style
的第一个祖先是否具有@font-style
值italic
。您可以使用模式化模板返回树,直到它找到具有@font-style
的祖先。
例。。。
<xsl:template match="cite">
<xsl:variable name="isItalic" as="xs:boolean">
<xsl:choose>
<xsl:when test="not(ancestor::*[@font-style[string()]])">
<xsl:sequence select="false()"/>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="." mode="isItalic"/>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<fo:inline font-style="{if ($isItalic) then 'normal' else 'italic'}">
<xsl:apply-templates/>
</fo:inline>
</xsl:template>
<xsl:template match="*" mode="isItalic" as="xs:boolean">
<xsl:choose>
<xsl:when test="parent::*[@font-style[string()]]">
<xsl:sequence select="if (parent::*/@font-style='italic') then
true() else false()"/>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select=".." mode="isItalic"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
这是在 XSLT 1.0 中执行此操作的另一种方法...
<xsl:template match="cite">
<xsl:variable name="font-style">
<xsl:choose>
<xsl:when test="not(ancestor::*[@font-style[string()]])">
<xsl:text>italic</xsl:text>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="." mode="getFontStyle"/>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<fo:inline font-style="{$font-style}">
<xsl:apply-templates/>
</fo:inline>
</xsl:template>
<xsl:template match="*" mode="getFontStyle">
<xsl:choose>
<xsl:when test="parent::*[@font-style[string()]]/@font-style='italic'">
<xsl:text>normal</xsl:text>
</xsl:when>
<xsl:when test="parent::*[@font-style[string()]]">
<xsl:text>italic</xsl:text>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select=".." mode="getFontStyle"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>