使用 XSL 确定(伪)二进制属性的状态



今天早上,我正在为 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-styleitalic。您可以使用模式化模板返回树,直到它找到具有@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>

相关内容

  • 没有找到相关文章

最新更新