4
votes

I currently have an XSL file that I use to transform XML into FO format (XSL-FO). The only problem is with the footers. I have a requirement to display a textual reference from the footer of each of the pages to one of the other pages. What this means is I need to make the footer text dynamic. For example, here's some abstract text from each of the pages:

page 1: Topic A
page 2: Topic B
page 3: Topic C, Subtopic of A
page 4: Topic D, Subtopic of A
page 5: Topic E, Subtopic of B

Imagine the "subtopic" part as the footer to display for each page.

Consider the following XML:

<DATA_DS>
    <LIST_ITEMS>
        <ITEMS>
            <isChild>0</isChild>
            <myvalue>abc</myvalue>
            <isLastChild>0</isLastChild>
        </ITEMS>
        <ITEMS>
            <isChild>1</isChild>
            <myvalue>def</myvalue>
            <isLastChild>0</isLastChild>
        </ITEMS>
        <ITEMS>
            <isChild>1</isChild>
            <myvalue>ghi</myvalue>
            <isLastChild>0</isLastChild>
        </ITEMS>
        <ITEMS>
            <isChild>1</isChild>
            <myvalue>xyz</myvalue>
            <isLastChild>1</isLastChild>
        </ITEMS>        
    </LIST_ITEMS>
</DATA_DS>

and this XSL:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="2.0"
      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
      xmlns:fo="http://www.w3.org/1999/XSL/Format">
  <xsl:output method="xml" indent="yes"/>
  <xsl:template match="/">
    <fo:root>
      <fo:layout-master-set>
          <fo:simple-page-master master-name="parentLOBPage-master" page-width="11in" page-height="8.5in" margin-left="1.3in" margin-right="0.65in" margin-top="0.35in" margin-bottom="0.35in">
              <fo:region-body region-name="body" margin-top="0.5in" margin-right="0.65in"/>
              <fo:region-after region-name="footer" extent="14mm" />
          </fo:simple-page-master>

          <fo:simple-page-master master-name="childLOBPage-master" page-width="11in" page-height="8.5in" margin-left="1.3in" margin-right="0.65in" margin-top="0.35in" margin-bottom="0.35in">
              <fo:region-body region-name="body" margin-top="0.5in" margin-right="0.65in"/>
              <fo:region-after region-name="footer" extent="14mm"/>
          </fo:simple-page-master>

          <fo:page-sequence-master master-name="parentLOBPage">
            <fo:repeatable-page-master-reference 
                master-reference="parentLOBPage-master"/>
          </fo:page-sequence-master>

          <fo:page-sequence-master master-name="childLOBPage">
            <fo:repeatable-page-master-reference 
                master-reference="childLOBPage-master"/>
          </fo:page-sequence-master>
      </fo:layout-master-set>

            <xsl:apply-templates/>

    </fo:root>
  </xsl:template>


  <xsl:template match="DATA_DS">
    <xsl:for-each-group select="LIST_ITEMS/ITEMS" 
                        group-adjacent="isChild">

      <xsl:choose>
        <xsl:when test="isChild = 0">
          <fo:page-sequence master-reference="parentLOBPage">


                    <fo:static-content flow-name="footer">

                            <fo:table width="100%" table-layout="fixed" margin-top="5mm">
                                <fo:table-column column-width="80%"/>
                                <fo:table-column column-width="20%"/>                               

                                <fo:table-body>
                                    <fo:table-row>
                                    <fo:table-cell>
                                            <fo:block text-align="left" font-family="Arial" font-size="7pt" font-weight="normal">parent footer</fo:block>
                                    </fo:table-cell>
                                    <fo:table-cell>
                                        <fo:block text-align="right" font-family="Arial" font-size="7pt" font-weight="normal">Page <fo:page-number/> of <fo:page-number-citation ref-id="last-page" /></fo:block>
                                    </fo:table-cell>
                                </fo:table-row>
                            </fo:table-body>
                        </fo:table>

                        </fo:static-content>                        

            <fo:flow flow-name="body">
              <xsl:for-each select="current-group()">
                <xsl:apply-templates select="."/>
              </xsl:for-each>
            </fo:flow>
          </fo:page-sequence>
        </xsl:when>

        <xsl:otherwise>
          <fo:page-sequence master-reference="childLOBPage">
                    <fo:static-content flow-name="footer">
                            <fo:table width="100%" table-layout="fixed" margin-top="5mm">
                                <fo:table-column column-width="80%"/>
                                <fo:table-column column-width="20%"/>                               

                                <fo:table-body>
                                    <fo:table-row>
                                    <fo:table-cell>
                                            <fo:block text-align="left" font-family="Arial" font-size="7pt" font-weight="normal">child footer: <xsl:value-of select="myvalue"/></fo:block>
                                    </fo:table-cell>
                                    <fo:table-cell>
                                        <fo:block text-align="right" font-family="Arial" font-size="7pt" font-weight="normal">Page <fo:page-number/> of <fo:page-number-citation ref-id="last-page" /></fo:block>
                                    </fo:table-cell>
                                </fo:table-row>
                            </fo:table-body>
                        </fo:table>

                        </fo:static-content>                        

            <fo:flow flow-name="body">

              <xsl:for-each select="current-group()">
                <xsl:apply-templates select="."/>
              </xsl:for-each>
              <fo:block id="last-page"/>
            </fo:flow>
          </fo:page-sequence>
        </xsl:otherwise>

      </xsl:choose>
    </xsl:for-each-group>
  </xsl:template>


  <xsl:template match="ITEMS">

            <fo:table width="100%" table-layout="fixed" margin-top="5mm">
                <fo:table-column column-width="20%"/>
                <fo:table-column column-width="80%"/>                               

                <fo:table-body>
                    <fo:table-row>
                    <fo:table-cell>
                            <fo:block text-align="left" font-family="Arial" font-size="10pt" font-weight="bold">big table</fo:block>
                        </fo:table-cell>
                    <fo:table-cell>
                            <fo:block text-align="left" font-family="Arial" font-size="10pt" font-weight="bold">some stuff</fo:block>
                        </fo:table-cell>                                            
                    </fo:table-row>
                </fo:table-body>
            </fo:table>

        <xsl:if test="isChild = 1 and isLastChild = 0">
                <fo:block page-break-after="always"/>
            </xsl:if>

  </xsl:template>  
</xsl:stylesheet>

Since I wrap most of the content of each page in a fo:table, and some tables overflow onto 2+ pages, I can't just put the "dynamic footer text" after each table because it won't display on every page then.

So, I suppose that my use of fo:static-content isn't appropriate, even though it does what I need for displaying the page numbers dynamically (i.e. page x of y). The output shows that for every child footer page the value displayed is "def", which is the first "child" in the list. So, fo:static-content is populating itself the first time is executed and doesn't update for subsequent pages...so my approach is wrong. I need some guidance on how to revise my approach...

Any suggestions on how I get footers working the way I need to for my XSL-FO situation? Thanks...

1

1 Answers

5
votes

Your code is not appropriately structured for dynamic content in static content.

The concept you are missing is that your footer needs to "retrieve markers" that you set at points on the fly in the flow. One footer for all pages retrieves one marker class from the content of the pages and you change the marker at points in your flow and the retrieval obtains the most recent marker (or other options).

So you need only a single footer that has your "Page x of y" bit, and you need to include a that retrieves a marker of a particular class. Then, in your flow, with all of your topics and sub-topics, and when you get to the first item of each you define a marker with the text you want to see in the footer.

The XSL-FO output your XSLT needs to produce is along the lines of:

  <fo:static-content>
     ... page x of y stuff ...
     <fo:retrieve-marker retrieve-class-name="topic"/>
  </fo:static-content>
  <fo:flow>
    <fo:table>
      ...
       <fo:table-cell>
         <fo:marker marker-class-name="topic">Topic A</fo:marker>
      ...
       <fo:table-cell>
         <fo:marker marker-class-name="topic">Topic B</fo:marker>
      ...
       <fo:table-cell>
         <fo:marker marker-class-name="topic">Topic C, Subtopic of A</fo:marker>
      ...
       <fo:table-cell>
         <fo:marker marker-class-name="topic">Topic D, Subtopic of A</fo:marker>
      ...
       <fo:table-cell>
         <fo:marker marker-class-name="topic">Topic E, Subtopic of B</fo:marker>

I suggest you review the frames titled "Dynamic content in static content" starting on page 257 of the free "Try and buy" preview of my PDF book at:

http://www.CraneSoftwrights.com/training/#pfux

There are nuances to the attributes for retrieval and positioning of the markers that are described there, with diagrams.