This morning I was working on implementing xsl-fo formatting for the xhtml <cite> tag. Typically you want citations to be italicized:
<xsl:template match="cite">
<fo:inline font-style="italic"><xsl:apply-templates/></fo:inline>
</xsl:template>
Of course there is this complication: if the surrounding text is already italicized, then you want the citation font-style to be normal for the purposes of contrast. The first, somewhat naive attempt at addressing this can be found in Doug Tidwell's IBM tutorial (http://ift.tt/15yTTtB):
<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>
This would be OK, except that xsl-fo allows for the font-style attribute in any block or inline tag. So imagine that in a somewhat modified flavor of html, the font-style attribute can appear in any (xhtml strict) block or inline tag which can contain text or children containing text. The puzzle I'm trying to solve is how can you then determine whether or not any particular citation should be italicized?
My first stab at solving the problem:
<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>
Of course it's clear that this doesn't work in every case:
<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>
The template above would set the font-style of the citation to normal because this condition would be the first one met:
<xsl:when test="ancestor::*[@font-style='italic']">
I've thought about something like
test="count(ancestor::*[@font-style='italic']) - count(ancestor::*[@font-style='normal') mod 2 = 0"
but this doesn't work, either, as the order of tags matters; i.e. it's perfectly legal to do something like this:
<div font-style="italic> ... <p font-style="italic"> ...</p></div>
I know how I would do this with a procedural language: count backwards through the ancestor list incrementing/decrementing an "italic" count variable, but I can't think of any way of doing this in XSL, given that variables are immutable.
No comments:
Post a Comment