In transforming a large XML text corpus (to a PDF, XSL 3.0, XSL:FO) I am running into a template problem with controlling what ultimately appears in the body of the output and what appears in the margin, resulting from one element. I'm not sure if this is an xsl or xsl:fo issue.
The problem is with the output of element <add type="margin_gloss">
, processed by templates <xsl:template match="seg[@type='dep_event']">
and <xsl:template match="add[@type='margin_gloss']">
in the example below. I expect the contents of <add type="margin_gloss">
to only appear in the margin; but it's persisting in the body as well.
This xml markup:
<corpus>
<deposition>
<text>
<deposition-title>Some foo title</deposition-title>
<seg type="dep_event"> Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam vitae venenatis
ante. Suspendisse posuere velit non nisi tincidunt, commodo faucibus neque volutpat.
Integer <add type="margin_gloss">This is a <foreign>foo</foreign> ma<supplied reason="added">rgin</supplied> note</add>
posuere laoreet sem eu scelerisque. Vestibulum purus risus, semper
vitae suscipit non, mal<supplied reason="added">esuada</supplied> ut massa. Sed et auctor erat.</seg>
<seg type="dep_event"> Suspendisse eu urna sed purus mattis placerat. Vestibulum <foreign>some English</foreign> scelerisque
lectus, in lobortis tortor fa<supplied reason="added">cilisis</supplied> eu. Donec mollis pulvinar varius. Nam eget
euismod ipsum, ac suscipit nunc. Sed volutpat non felis id varius. </seg>
</text>
</deposition>
</corpus>
Processed by this xsl:fo:
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:fo="http://www.w3.org/1999/XSL/Format"
xmlns:xd="http://www.pnp-software.com/XSLTdoc"
version="3.0">
<xsl:template match="/">
<fo:root>
<fo:layout-master-set>
<fo:simple-page-master
master-name="page-recto"
page-height="29.7cm" page-width="21cm"
margin-top="2cm" margin-bottom="2cm"
margin-left="2cm" margin-right="1cm">
<fo:region-body
region-name="xsl-region-body"/>
</fo:simple-page-master>
</fo:layout-master-set>
<fo:page-sequence master-reference="page-recto">
<fo:flow flow-name="xsl-region-body"
font-family="Times" font-weight="normal"
font-size="8pt" space-before="8pt" space-after="8pt"
text-align="justify" end-indent="120pt">
<xsl:apply-templates/>
</fo:flow>
</fo:page-sequence>
</fo:root>
</xsl:template>
<xsl:template match="text">
<fo:block
page-break-inside="avoid"
font-size="9pt" font-weight="bold"
padding-bottom="1cm" end-indent="120pt">
<xsl:apply-templates/>
</fo:block>
</xsl:template>
<xsl:template match="seg[@type='dep_event']">
<fo:block
font-family="Times" font-weight="normal"
font-size="8pt" space-before="8pt"
space-after="8pt" text-align="justify"
end-indent="2.5in">
<xsl:if test=".//add[@type='margin_gloss']">
<fo:float float="right">
<fo:block-container width="2in" margin="10pt">
<fo:block font-size="7pt">
<xsl:apply-templates select=".//add[@type='margin_gloss']"/>
</fo:block>
</fo:block-container>
</fo:float>
</xsl:if>
<xsl:apply-templates/>
</fo:block>
</xsl:template>
<xsl:template match="add[@type='margin_gloss']">
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="foreign">
<fo:inline font-style="italic">
<xsl:apply-templates/>
</fo:inline>
</xsl:template>
<xsl:template match="supplied[@reason='added']">
<xsl:text>[</xsl:text><xsl:apply-templates/><xsl:text>]</xsl:text>
</xsl:template>
</xsl:stylesheet>
Produces this problem output - the formatted contents of <add type="margin_gloss">
(I've highlighted in yellow) should only appear in the margin, not the body:
I've tried various forms of <apply-templates>
but they either mangle/ignore the markup in the margin note (eg: <xsl:apply-templates select="descendant::add[@type='margin_gloss']/text()"/>
), or disappear the margin note altogether.
I should note that I am using xsl:fo processor RenderX for full support of <fo:float>
.
Thanks in advance.
The problem is that your <add type="margin_gloss">
is being selected twice. First by this line...
<xsl:apply-templates select=".//add[@type='margin_gloss']"/>
And then by this line...
<xsl:apply-templates/>
One way to get around this, is to change the explicit xsl:apply-templates
to this...
<xsl:for-each select=".//add[@type='margin_gloss']">
<xsl:apply-templates />
</xsl:for-each>
Then, change the template matching add[@type='margin_gloss']
to this, as this will prevent it being processed a second time by the xsl:apply-templates
<xsl:template match="add[@type='margin_gloss']" />
So, the two relevant templates will look like this....
<xsl:template match="seg[@type='dep_event']">
<fo:block
font-family="Times" font-weight="normal"
font-size="8pt" space-before="8pt"
space-after="8pt" text-align="justify"
end-indent="2.5in">
<xsl:if test=".//add[@type='margin_gloss']">
<fo:float float="right">
<fo:block-container width="2in" margin="10pt">
<fo:block font-size="7pt">
<xsl:for-each select=".//add[@type='margin_gloss']">
<xsl:apply-templates />
</xsl:for-each>
</fo:block>
</fo:block-container>
</fo:float>
</xsl:if>
<xsl:apply-templates/>
</fo:block>
</xsl:template>
<xsl:template match="add[@type='margin_gloss']"/>