XSL:FO Page-Number() function with leading zeros - xslt

Lets say I want to print a page number "01" as two separate digits 0 and 1 from 1 to 9
0X-> 01,02,03....
from 10 to 99
10,11,12
<fo:table-cell xsl:use-attribute-sets="TableCellBorder">
<fo:block>
<xsl:value-of select="substring(<fo:page-number/>, 1, 1)"/> //0 or first page-number digit
</fo:block>
</fo:table-cell>
<fo:table-cell xsl:use-attribute-sets="TableCellBorder">
<fo:block>
<xsl:value-of select="substring(<fo:page-number/>, 2, 1)"/>//second page-number digit
</fo:block>
</fo:table-cell>
any ideas how to do this?

<fo:page-sequence master-reference="mymaster" format="01">
...
<fo:page-number/>
...
</fo:page-sequence>
Described here, the only trick is figuring out where to place it.
Sorry, tested with XEP only; no idea if FOP supports it.
UPD. Would you consider adding the words of "leading zeros" in order to make the article searchable better?

This is not possible.
<fo:page-number/> is a XSL-FO construct. It does not get a value until the XSL-FO processor runs. It cannot be manipulated in the XSLT stylesheet that generates the XSL-FO markup.

Related

XSL-FO 2.0: Prevent page-break inside table

I can't find a way to prevent a page break inside a table in the RTF output.
I've tried a lot of combinations of keep-together / keep-with-next but nothing worked for me. The actual version has a parent fo:block with the attribute keep-together.within-page="always" including the whole table.
The problem only occurs when a RTF is generated. The PDF is correct and no page break inside a table exists. The table has a header-row and 3 data-rows. In the RTF there is a page-break after the header-row and the first 2 data-rows. On the next page the header is repeated and the last data-row is generated.
It's very important that the tables don't include a page-break.
Here is the relevant XSLT-Stylesheet code:
<fo:block keep-together.within-page="always" >
<xsl:for-each select="block">
<xsl:call-template name="drawData"></xsl:call-template>
</xsl:for-each>
<fo:table text-align="center">
<xsl:for-each select="row[#type='declare'][1]/column">
<fo:table-column column-number="position()" border-style="solid" border-color="#000000" border-width="0.5pt">
<xsl:attribute name="column-width"><xsl:value-of select="#width"/></xsl:attribute>
</fo:table-column>
</xsl:for-each>
<xsl:if test="row[#type='header']">
<fo:table-header>
<fo:table-row keep-together.within-page="2" background-color="#0000FF" color="#FFFFFF">
<xsl:for-each select="row[#type='header'][1]/column/block">
<fo:table-cell border-style="solid" border-color="#000000" border-width="0.5pt">
<xsl:attribute name="number-columns-spanned">
<xsl:value-of select="count(../../../row[#type='declare']/column) div count(../../../row[#type='declare'])"/>
</xsl:attribute>
<xsl:call-template name="drawData"></xsl:call-template>
</fo:table-cell>
</xsl:for-each>
</fo:table-row>
</fo:table-header>
</xsl:if>
<fo:table-body>
<xsl:for-each select="row[not(#type='header')]">
<fo:table-row keep-together.within-page="2">
<xsl:for-each select="column/block">
<fo:table-cell border-style="solid" border-color="#000000" border-width="0.5pt">
<xsl:call-template name="drawData"></xsl:call-template>
</fo:table-cell>
</xsl:for-each>
</fo:table-row>
</xsl:for-each>
</fo:table-body>
</fo:table>
</fo:block>
A screenshot of the relevant table:
At the moment (FOP version 2.1), the RTF output has a few limitations compared to the PDF output; in particular, it does not support keep properties.
The linked page states that
RTF output is currently unmaintained
and keeps are
supported by the RTF library but not tied into the RTFHandler
so, while it is probably unlikely that this feature will be fixed in future versions without external help, it could be relatively easy to implement it (in which case it would be a good idea to submit a patch).

How to display blocks in multiple rows in XSL-FO?

I am trying to add images in multiple rows.
Here is my code:
<fo:block-container reference-orientation="90" >
<xsl:for-each select="Icons/Icon">
<fo:block>
<fo:external-graphic src="{#Source}"/>
</fo:block>
</xsl:for-each>
</fo:block-container>
The <fo:block-container> is placed in an <fo:table-cell>.
You can see examples below where text is other part of the table.
How it looks:
But it should look like this:
I tried to add width for block-container, but it doesn't help.
It can't wrap because you're using a rotated fo:block-container, so what you're seeing is the rotated equivalent of blocks overflowing past the bottom of the page.
It's not clear to me why you're rotating the images, but you could put each graphic inside a separate fo:inline-container and set the reference-orientation on each. (See https://www.w3.org/TR/xsl11/#fo_inline-container)
<fo:table-cell>
<fo:block>
<fo:inline-container reference-orientation="90">
<fo:block>
<fo:external-graphic src="..." />
</fo:block>
</fo:inline-container>
...
</fo:block>
</fo:table-cell>

XSL-FO Overflow Handling for fo:inline-container Elements

XSL-FO Overflow Handling for fo:inline-container Elements
My question is: How is it possible to break contents (e.g. fo:block elements) inside a fo:inline-container to a new page if the iherit contents are too long for the current one?
Used Fomatters: AHF 6.2, Apache FOP 2.1
The transformation has to work for both formatters; so a simple solution with fo:float elements is not possible.
Here is a short code extract:
<xsl:template match="myElement">
<fo:block>
<fo:inline-container inline-progression-dimension="33.333%">
<fo:block>
Marginalia Headline
</fo:block>
</fo:inline-container>
<fo:inline-container inline-progression-dimension="66.666%">
<fo:block>
Imagine this is a very long text ...
</fo:block>
<fo:block>
Imagine this is a very long text ...
</fo:block>
<fo:block>
Imagine this is a very long text ...
</fo:block>
<!-- MANY MORE fo:blocks -->
</fo:inline-container>
</fo:block>
</xsl:template>
The thing is, the contents are overflowing the fo:inline-container but are not breaking onto a new page. I think this has something to do with the surrounding fo:block element that keeps everything on a single page.
Any advice would be helpful here. Thank you in advance!
What works
Using fo:list-block
(Ok, you said you'd rather not use this trick ... anyway this works and could be used as a last resort)
You can put the marginalia in the fo:list-item-label and the "normal" text in the fo:list-item-body:
<fo:list-block provisional-distance-between-starts="33.333%">
<fo:list-item>
<fo:list-item-label end-indent="label-end()">
<fo:block>
Marginalia Headline
</fo:block>
</fo:list-item-label>
<fo:list-item-body start-indent="body-start()">
<fo:block>
Lorem ipsum dolor ...
</fo:block>
<!-- other blocks ... -->
</fo:list-item-body>
</fo:list-item>
</fo:list-block>
Using overflowing fo:block-container
Alternatively, you could use a flatter sequence of formatting objects, putting the marginalia into a zero-height block container, so that the following block of normal text will start at the same height:
<fo:block-container height="0pt" overflow="visible" keep-with-next.within-page="always">
<fo:block end-indent="66.666%">
Marginalia Headline
</fo:block>
</fo:block-container>
<fo:block start-indent="33.333%">
Lorem ipsum dolor ...
</fo:block>
<!-- other blocks ... -->
Note that this solution can lead to a marginalia overflowing into the page bottom margin or overlapping the next marginalia if it produces more than X lines, where X is the orphans property of its corresponding normal text (for example, marginalia is three lines long while the normal text has orphans="2").
What does not work
Using fo:float
Even if FOP supports side-floats, I don't think using them would achieve the desired output, as the text would flow around it, returning to use all the available horizontal space as soon as possible:
<fo:block>
<fo:float float="left">
<fo:block width="33.333%" background-color="#AAFFFF">Marginalia Headline</fo:block>
</fo:float>
<fo:block background-color="#FFAAFF">
Lorem ipsum dolor ...
</fo:block>
<!-- other blocks ... -->
</fo:block>
Using fo:inline-container
I think the code in the question does not work as expected not because of something missing in the outer fo:block, but because of something missing in the fo:inline-container containing the long text: the overflow attribute.
If unspecified, its default value is "auto" which means the formatting object processor can do as it likes (probably showing the content even if overflows). With overflow="repeat" the processor should, if needed, create other areas, so that the content will be split into pages:
<fo:block>
<fo:inline-container inline-progression-dimension="33.333%">
<fo:block>
Marginalia Headline
</fo:block>
</fo:inline-container><fo:inline-container inline-progression-dimension="66.666%" overflow="repeat">
<fo:block>
Lorem ipsum dolor ...
</fo:block>
<!-- other blocks ... -->
</fo:inline-container>
</fo:block>
FOP, however, does not support overflow="repeat" (I cannot test with Antenna House XslFormatter, but the conformance page says it is supported).
(Disclosure: I am an inactive FOP developer)

Page break inside table XSL-FO

I have an XSL-FO stylesheet for a table.
<fo:page-sequence master-reference="defaultPage">
<fo:flow flow-name="xsl-region-body">
<fo:table table-layout="fixed" width="100%">
<fo:table-column column-width="9pt"/>
<fo:table-column column-width="30pt"/>
<fo:table-column column-width="150pt"/>
<fo:table-header>
<fo:table-row>
<fo:table-cell>
<fo:block><xsl:text>Column 1</xsl:text></fo:block>
</fo:table-cell>
<fo:table-cell>
<fo:block><xsl:text>Column 2</xsl:text></fo:block>
</fo:table-cell>
<fo:table-cell>
<fo:block><xsl:text>Column 3</xsl:text></fo:block>
</fo:table-cell>
</fo:table-row>
</fo:table-header>
<fo:table-body>
<fo:table-row>
<xsl:apply-templates select="rbrOcjena"/>
<xsl:apply-templates select="sifPred"/>
<xsl:apply-templates select="nazPred"/>
</fo:table-row>
</fo:table-body>
</fo:table>
</fo:flow>
</fo:page-sequence>
The table can have many rows, so I'd like to break it on new page when it comes to the end of current, when generating PDF. Also, I would like to repeat table header on new page, if that's possible. What attributes should I put in the table tag to make it so?
Thanks!
The table can have many rows, so I'd like to break it on new page when
it comes to the end of current
Without seeing your XSL-FO code, it is difficult to answer this. Please show it. But generally, this is done with keeps and breaks. For example:
<fo:table-row keep-together.within-page="always">
I would like to repeat table header on new page, if that's possible.
What attributes should I put in the table tag to make it so?
Instructing an XSL-FO processor to repeat a number of rows at the top of every page is not done via an attribute to fo:table. Instead, the rows that are to be repeated are put inside fo:table-header:
<fo:table-header>
<fo:table-row>
<fo:table-cell>
<!--Block and text content-->
</fo:table-cell>
</fo:table-row>
</fo:table-header>
Then, the default behaviour of the processor should be to repeat the header rows after a page break. That's because the omit-header-at-break attribute of fo:table is set to "false" by default.
The most obvious reason for this is that it is immediately clear which rows belong to the header and should thus be repeated. If this was just a reference in an attribute of fo:table it would be harder to identify multiple rows as the header. You will find the relevant part of the XSL specification here.
I've faced similar scenario...
Try below code...
<fo:table-row>
<xsl:if test="position() != 1">
<xsl:attribute name="break-before">page</xsl:attribute></i>
.
.
.

How to insert a white space between two (inline) elements?

Context
I am creating an XSL-FO document to convert my XML text to PDF.
In the XSL-FO, I have two consecutive inline elements, I would like a white space between them:
<fo:block>
<xsl:number/> <xsl:value-of select="#title"/>
</fo:block>
The expected result would be:
1 Introduction
Instead, I get
1Introduction
It seem XML do not consider this white space.
Attempts
I have tried several possible solutions, without success:
<fo:block>
<xsl:number/><fo:inline white-space="pre"> </fo:inline><xsl:value-of select="#title"/>
</fo:block>
or
<fo:block>
<xsl:number/><fo:inline margin-left="0.5cm"><xsl:value-of select="#title"/></fo:inline>
</fo:block>
None of those ideas produce an acceptable result.
The question:
How to include a white space between two (inline) elements?
Try:
<fo:block>
<xsl:number/>
<xsl:text> </xsl:text>
<xsl:value-of select="#title"/>
</fo:block>
Or:
<fo:block>
<xsl:number/>
<xsl:value-of select="concat(' ', #title)"/>
</fo:block>
The problem with
<fo:inline white-space="pre"> </fo:inline>
is that by default all whitespace-only text nodes within a stylesheet are stripped out, with the exception of those inside xsl:text elements. You can override this with xml:space="preserve"
<fo:inline xml:space="preserve" white-space="pre"> </fo:inline>
All whitespace text nodes that are descendants of an element with this attribute will be kept. Note that unlike normal namespaces you don't need to (and indeed are not allowed to) declare the xml: namespace prefix.
You can also use the following:
&nbsp;