XSL:FO float for displaying margin notes - breaks

2019-05-11 07:44发布

问题:

I have a large medieval manuscript transcribed into XML (using TEI schema). I am using xsl:fo and Apache FOP to process into PDF. The file is constructed using nested <body>, <p>, <seg> as shown below. Occasionally <add> is used for margin notes.

<body>
   <p>
    <title>title here</title>
    <seg>Lorem ipsum dolor sit amet, consectetur adipiscing elit. 
        Quisque a orci non mauris convallis imperdiet consequat nec 
        purus. Cras mollis lacus vel lectus facilisis, non
        hendrerit velit tempor. Phasellus tempor urna vel accumsan 
        dignissim.</seg>
    <seg>Aliquam porta eu nunc sed laoreet. 
        Sed<add type='margin_gloss'>Some margin note here</add> 
        non nulla consectetur, lobortis tortor ac,
        placerat nunc. Nulla viverra finibus est nec efficitur. Donec 
        nisi nisl, tincidunt dapibus purus pretium, rhoncus volutpat 
        tortor. Cras fringilla tellus tortor, at
        ultricies mi cursus at. Nulla facilisi.</seg>
    <seg>Quisque id mi nisl. In in mauris id leo malesuada hendrerit. 
        Orci varius natoque
        penatibus et magnis dis parturient montes, nascetur ridiculus 
        mus. Nulla sit amet
        commodo mauris.</seg>
  </p>
</body>

The xml file is massive, and so there is one master xml file which uses <xi:include>s to bring hundreds of these documents in order to compose the complete manuscript.

I have successfully processed this into a PDF with the following basic instructions:

  <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="body/p">
     <fo:block 
         page-break-inside="avoid"
         font-size="9pt" font-weight="bold" 
         padding-bottom="1cm" end-indent="120pt">
         <xsl:value-of select="tei:title"/>
         <xsl:apply-templates/>
     </fo:block>
   </xsl:template>


   <xsl:template match="seg">
      <fo:block id="@xml:id"
          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:block>
    </xsl:template>

This gives me a successful result like this page:

I've indented the right side (end) in order to make room for the margin notes. For example, in the 4th <seg> of the first <p>, there is a margin note 'Fabri +'. It is encoded <add type=margin_gloss>Fabri +</add>

I add the following template to 'float' the margin gloss:

<xsl:template match="body/p//add[@type='margin_gloss']">
     <fo:float float="end">
            <fo:block-container>
                <fo:block>
                    <xsl:value-of select="./s/text()"/>
                </fo:block>
            </fo:block-container>
        </fo:float>

</xsl:template>

And I get this disaster (the red text/arrows are my guides to the problems). The template with float has done 3 things which I cannot fathom. The float 'should' appear beside the 4th segment, but instead is below, merged with the next <p>; the 4th <seg> has disappeared; and the following <p>'s indent is reduced.

回答1:

Well, not an answer for you because you are using FOP and it has very limited support for floats. I took you example, expanded it a bit with content and removed some strange things like setting the ID as you did.

This XML:

<body>
<p>
    <title>title here</title>
    <seg>1 Lorem ipsum dolor sit amet, consectetur adipiscing elit. 
        Quisque a orci non mauris convallis imperdiet consequat nec 
        purus. Cras mollis lacus vel lectus facilisis, non
        hendrerit velit tempor. Phasellus tempor urna vel accumsan 
        dignissim.</seg>
    <seg>2 note Aliquam porta eu nunc sed laoreet. 
        Sed<add type='margin_gloss'>Some margin note here</add> 
        non nulla consectetur, lobortis tortor ac,
        placerat nunc. Nulla viverra finibus est nec efficitur. Donec 
        nisi nisl, tincidunt dapibus purus pretium, rhoncus volutpat 
        tortor. Cras fringilla tellus tortor, at
        ultricies mi cursus at. Nulla facilisi.</seg>
    <seg>3 Quisque id mi nisl. In in mauris id leo malesuada hendrerit. 
        Orci varius natoque
        penatibus et magnis dis parturient montes, nascetur ridiculus 
        mus. Nulla sit amet
        commodo mauris.</seg>
    <seg>4 Quisque id mi nisl. In in mauris id leo malesuada hendrerit. 
        Orci varius natoque
        penatibus et magnis dis parturient montes, nascetur ridiculus 
        mus. Nulla sit amet
        commodo mauris.</seg>
    <seg>5 Quisque id mi nisl. In in mauris id leo malesuada hendrerit. 
        Orci varius natoque
        penatibus et magnis dis parturient montes, nascetur ridiculus 
        mus. Nulla sit amet
        commodo mauris.</seg>
    <seg>6 note Aliquam porta eu nunc sed laoreet. 
        Sed<add type='margin_gloss'>Some margin note here 2</add> 
        non nulla consectetur, lobortis tortor ac,
        placerat nunc. Nulla viverra finibus est nec efficitur. Donec 
        nisi nisl, tincidunt dapibus purus pretium, rhoncus volutpat 
        tortor. Cras fringilla tellus tortor, at
        ultricies mi cursus at. Nulla facilisi.</seg>
    <seg>7 Quisque id mi nisl. In in mauris id leo malesuada hendrerit. 
        Orci varius natoque
        penatibus et magnis dis parturient montes, nascetur ridiculus 
        mus. Nulla sit amet
        commodo mauris.</seg>
    <seg>8 Quisque id mi nisl. In in mauris id leo malesuada hendrerit. 
        Orci varius natoque
        penatibus et magnis dis parturient montes, nascetur ridiculus 
        mus. Nulla sit amet
        commodo mauris.</seg>
</p>
</body>

Processed with this XSL:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format" 
version="1.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="body/p">
    <fo:block 
        page-break-inside="avoid"
        font-size="9pt" font-weight="bold" 
        padding-bottom="1cm" end-indent="120pt">
        <xsl:value-of select="title"/>
        <xsl:apply-templates/>
    </fo:block>
</xsl:template>

<xsl:template match="add">
    <fo:inline font-style="italic">
        <xsl:apply-templates/>
    </fo:inline>
</xsl:template>

<xsl:template match="seg">
    <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="descendant::add[@type='margin_gloss']">
            <fo:float float="right">
                <fo:block-container width="2in" border="1pt solid black" margin="10pt">
                    <fo:block>
                        <xsl:apply-templates select="add[@type='margin_gloss']"/>
                    </fo:block>
                </fo:block-container>
            </fo:float>
        </xsl:if>
        <xsl:apply-templates select="text()"/>
    </fo:block>
</xsl:template>
</xsl:stylesheet>

Results in this PDF when using RenderX XEP showing your floating Notes. If I use Apache FOP 2.1, they are totally missing as are the paragraphs that have the float in them. This totally indicates to me that FOP does not support this float, you should contact them for support.