Generating PDF in 11 * 17 (Landscape) with XSLT - pdf

I have this requirement wherein I need to create a PDS in 11 * 17 size and in landscape format with XSLT. I am able to create PDF in A4 page size using XSl FO.
My XSLT is as follow:
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format" font-family = "Helvetica" font-size = "10px">
<fo:layout-master-set>
<fo:simple-page-master margin-bottom="0.5cm" margin-left="0.75cm" margin-right="0.75cm" margin-top="0.5cm" master-name="first" page-height="27.9cm" page-width="21.6cm">
<fo:region-body margin-bottom = "0.5cm" margin-top = "0.25cm"/>
<fo:region-before extent = "0cm"/>
<fo:region-after extent = "0.5cm"/>
</fo:simple-page-master>
</fo:layout-master-set>
<xsl:for-each select="Rowsets">
<fo:page-sequence master-reference="first">
<fo:static-content flow-name="xsl-region-after">
<fo:block font-size="8pt" line-height="6pt" text-align-last="justify">
Shift Report
<fo:inline id="Date">
Date [currentDate]
</fo:inline>
<fo:leader leader-pattern = "space"/>
Page
<fo:page-number/>
</fo:block>
</fo:static-content>
<fo:flow flow-name="xsl-region-body">
<xsl:for-each select="Rowset">
<xsl:choose>
<xsl:when test="Columns/Column[1]/#Description = 'Break'">
<fo:block page-break-before="always" />
</xsl:when>
<xsl:otherwise>
<fo:table border-color="black" border-style="solid" border-width="1pt" table-layout="fixed" width="100%">
<xsl:variable name="columns">
<xsl:value-of select="count(Columns/Column)" />
</xsl:variable>
<xsl:for-each select="Columns/Column">
<xsl:choose>
<xsl:when test="position()<2">
<fo:table-column column-width="62pt" />
</xsl:when>
<xsl:when test="position()>1 and position()<4">
<fo:table-column column-width="40pt" />
</xsl:when>
<xsl:when test="position()>4 and position()<6">
<fo:table-column column-width="40pt" />
</xsl:when>
<xsl:when test="position()>8">
<fo:table-column column-width="60pt" />
</xsl:when>
<xsl:otherwise>
<fo:table-column />
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
<fo:table-body font-size="10pt">
<fo:table-row height="13pt">
<fo:table-cell background-color="#000000" border-style="solid" border-width="1pt" padding-left="5pt" padding-top="5pt" number-columns-spanned="{$columns}">
<fo:block font-weight="bold" text-align="center" color="#FFFFFF">
Shift Report
</fo:block>
</fo:table-cell>
</fo:table-row>
<fo:table-row height="13pt">
<xsl:for-each select="Columns/Column">
<fo:table-cell background-color="#CCCCCC" border-style="solid" border-width="1pt" padding-left="5pt" padding-top="5pt">
<fo:block font-weight="bold" text-align="left">
<xsl:value-of select="translate(#Name,'_',' ')" />
</fo:block>
</fo:table-cell>
</xsl:for-each>
</fo:table-row>
<xsl:for-each select="Row">
<fo:table-row height="13pt">
<xsl:for-each select="child::*">
<fo:table-cell background-color="#FFFFFF" border-style="solid" border-width="1pt" padding-left="5pt" padding-top="5pt">
<fo:block font-weight="normal" text-align="left">
<xsl:value-of select="." />
</fo:block>
</fo:table-cell>
</xsl:for-each>
</fo:table-row>
</xsl:for-each>
</fo:table-body>
</fo:table>
<fo:block text-indent="2pc" space-after="7pt" space-before.minimum="6pt" space-before.optimum="8pt" space-before.maximum="10pt">
</fo:block>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
</fo:flow>
</fo:page-sequence>
</xsl:for-each>
</fo:root>
</xsl:template>
</xsl:stylesheet>
I am not sure where does have to make change in order to accomodate 11 * 17 size and landscape orientation.
Also, one of the column(header) name is "QualityPercent". I would like to change it to "Quality%"
Can anyone help?

Change page-height="27.9cm" page-width="21.6cm" to page-height="11in" page-width="17in".
There's also the size shorthand (see https://www.w3.org/TR/xsl11/#size). If it's supported, you can use size="17in 11in". Some formatters (including AH Formatter: https://www.antenna.co.jp/AHF/help/en/ahf-ext.html#axf.size) recognise some set of keywords for the paper size, such that you can also use size="Ledger".
Edited:
Change:
<xsl:value-of select="translate(#Name,'_',' ')" />
to
<xsl:choose>
<xsl:when test="contains(#Name, 'Percent')">
<xsl:value-of select="substring-before(#Name, 'Percent')" />
<xsl:text>%</xsl:text>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="translate(#Name,'_',' ')" />
</xsl:otherwise>
</xsl:choose>
If you were using XSLT 2.0 (or 3.0), you could use replace() to more easily and accurately replace Percent with % in any #Name value.

Related

We are printing images to a pdf using XSL fo. our aim is to print them in row wise but those are printing in column wise. Any suggestions please

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.1" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format" exclude-result-prefixes="fo" xml:space="preserve">
<xsl:output method="xml" version="1.0" omit-xml-declaration="no" indent="yes"/>
<xsl:template match="assets">
<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
<fo:layout-master-set>
<fo:simple-page-master master-name="one" page-width="216mm" page-height="279mm" margin-top="10mm" margin-bottom="5mm" margin-left="10mm" margin-right="10mm">
<fo:region-body column-count="5" margin-top="1cm" margin-bottom="1cm"/>
<fo:region-before extent="1cm"/>
<fo:region-after extent="1cm"/>
</fo:simple-page-master>
</fo:layout-master-set>
<fo:page-sequence master-reference="one">
<fo:static-content flow-name="xsl-region-before">
<fo:table table-layout="fixed" width="100%" font-size="16pt" text-align="center">
<fo:table-column column-width="proportional-column-width(1)"/>
<fo:table-body>
<fo:table-row>
<fo:table-cell>
<fo:block>
<xsl:value-of select="title"/>
</fo:block>
</fo:table-cell>
</fo:table-row>
</fo:table-body>
</fo:table>
</fo:static-content>
<!--footer-->
<fo:static-content flow-name="xsl-region-after">
<fo:block font-size="8pt" font-family="Arial" text-align="left">All rights reserved.</fo:block>
<fo:block font-family="Arial" font-size="8pt" text-align="right">Page <fo:page-number/>
</fo:block>
</fo:static-content>
<!-- body -->
<fo:flow flow-name="xsl-region-body">
<xsl:apply-templates select="assetExport"/>
</fo:flow>
</fo:page-sequence>
</fo:root>
</xsl:template>
<xsl:variable name="width" select="#displayValue"/>
<xsl:template match="assetExport">
<fo:block-container border-color="#D3D3D3" border-style="solid" border-width=".8px" margin-top="4mm" keep-together.within-column="always" width="36mm" height="56mm" scaling="uniform">
<xsl:apply-templates select="thumbnail"/>
<xsl:apply-templates select="metadata"/>
</fo:block-container>
</xsl:template>
<xsl:template match="metadata">
<xsl:apply-templates select="property"/>
</xsl:template>
<!-- Render the images -->
<xsl:template match="thumbnail">
<xsl:variable name="src" select="."/>
<xsl:choose>
<xsl:when test="$src = ''">
<fo:block-container>
<fo:block width="30mm" height="40mm" font-weight="bold" font-size="12pt" text-indent="5mm" margin-top="3mm" margin-bottom="2mm" margin-left="2mm" margin-right="2mm">
<xsl:text width="30mm" height="40mm">No Preview available</xsl:text>
</fo:block>
</fo:block-container>
</xsl:when>
<xsl:otherwise>
<fo:block margin-left="2mm" margin-right="2mm" margin-top="0mm">
<fo:external-graphic src="url(file:///{$src})" width="32mm" text-align="center" display-align="center" content-width="scale-to-fit" height="32mm" content-height="scale-to-fit" scaling="uniform"/>
</fo:block>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<!-- Render the metadata WITH Prompt -->
<xsl:template match="property">
<xsl:choose>
<xsl:when test="#prompt = 'Expiration Date'">
<fo:block margin-left="2mm" wrap-option="wrap" width="34mm" height="30mm" font-family="Arial" font-size="8pt" color="black">
<xsl:value-of select="(concat('Expiration Date: ',substring(child::property-value/attribute::displayValue,0,11)))"/>
</fo:block>
</xsl:when>
<xsl:otherwise>
<fo:block margin-left="2mm" wrap-option="wrap" width="34mm" height="30mm" font-family="Arial" font-size="8pt" color="black">
<xsl:value-of select="attribute::prompt"/>
<xsl:text> : </xsl:text>
<xsl:value-of select="child::property-value/attribute::displayValue"/>
</fo:block>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>

How to convert some text in paragraph into bold xsl fo?

This is how my xml looks like:
xml:
<Documents>
<Document>
<Note>
<Header>
<HeaderText> <b>Need Help?</b> Contact Our Customer Happiness Team
by phone <b>0345 00002662</b>
Mon-Fri 9am-7pm
</HeaderText>
</Header>
</Note>
</Document>
</Documents>
I want to convert some text in HeaderText in bold. E.g Need Help? Contact Our Customer Happiness Team
by phone 0345 00002662 Mon-Fri 9am-7pm
Xslt:
<fo:table-header text-align="left" border-width="0mm">
<fo:table-row margin-left="1cm" font-family="Avenir" font-size="14pt">
<fo:table-cell>
<fo:block padding-top="0cm">
<xsl:value-of select="HeaderText" />
</fo:block>
</fo:table-cell>
</fo:table-row>
</fo:table-header>
The <b>Need Help?</b> is just text to the XSLT processor and the XSL-FO formatter.
This is similar to XSLT - How to treat inline/escaped XML within a node as nested nodes. The advice there doesn't get beyond doing it in two passes or using XSLT 2.0 or 3.0.
If <b> is the only non-element that you need to convert into real markup, then you can do it with a recursive template:
<xsl:template match="text()[contains(., '<b>')]"
name="unescape-bold">
<xsl:param name="text" select="." />
<xsl:choose>
<xsl:when test="not(contains($text, '<b>'))">
<xsl:value-of select="$text" />
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="substring-before($text, '<b>')" />
<fo:inline font-weight="bold">
<xsl:value-of
select="substring-before(substring-after($text, '<b>'),
'</b>')" />
</fo:inline>
<xsl:call-template name="unescape-bold">
<xsl:with-param name="text"
select="substring-after($text, '</b>')" />
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
For your sample, this gives:
<fo:inline font-weight="bold">Need Help?</fo:inline> Contact Our Customer Happiness Team
by phone <fo:inline font-weight="bold">0345 00002662</fo:inline>
Mon-Fri 9am-7pm
Check this Code:-
<fo:table-header text-align="left" border-width="0mm">
<fo:table-row margin-left="1cm" font-family="Avenir" font-size="14pt">
<fo:table-cell>
<fo:block padding-top="0cm">
<xsl:apply-templates/>
</fo:block>
</fo:table-cell>
</fo:table-row>
</fo:table-header>
<xsl:template match="bold">
<fo:inline font-weight="bold">
<xsl:apply-templates/>
</fo:inline>
</xsl:template>

I want to split the string stored in a variable and store the obtained values in variable using xslt

<xsl:variable name="AAM" select="//AAM"/>
AAM will have string value_1,value_2,value_3,value_4
I then want to split this and store in 4 variables :
seg1,
seg2,
seg3,
seg4
Assuming the below as your input:
<?xml version="1.0" encoding="UTF-8"?>
<body>
<AAM>value_1,value_2,value_3,value_4</AAM>
</body>
An XSLT 2.0 solution to split a comma separated string can be:
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes" />
<xsl:variable name="AAM" select="//AAM" />
<xsl:template match="body">
<body>
<xsl:variable name="separator" select="','" />
<xsl:for-each select="tokenize($AAM,$separator)">
<xsl:element name="seg{position()}">
<xsl:value-of select="normalize-space(.)" />
</xsl:element>
</xsl:for-each>
</body>
</xsl:template>
http://xsltransform.net/6qaFCET/1
Edit: (Based on commented)
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes" />
<xsl:variable name="AAM" select="//AAM" />
<xsl:template match="body">
<body>
<xsl:variable name="separator" select="','" />
<xsl:for-each select="tokenize($AAM,$separator)">
<xsl:choose>
<xsl:when test="position() = 1">
<xsl:variable name="seg1">
<xsl:value-of select="normalize-space(.)" />
</xsl:variable>
<xsl:copy-of select="$seg1" />
<xsl:text>
</xsl:text>
</xsl:when>
<xsl:when test="position() = 2">
<xsl:variable name="seg2">
<xsl:value-of select="normalize-space(.)" />
</xsl:variable>
<xsl:copy-of select="$seg2" />
<xsl:text>
</xsl:text>
</xsl:when>
<xsl:when test="position() = 3">
<xsl:variable name="seg3">
<xsl:value-of select="normalize-space(.)" />
</xsl:variable>
<xsl:copy-of select="$seg3" />
<xsl:text>
</xsl:text>
</xsl:when>
<xsl:when test="position() = 4">
<xsl:variable name="seg4">
<xsl:value-of select="normalize-space(.)" />
</xsl:variable>
<xsl:copy-of select="$seg4" />
<xsl:text>
</xsl:text>
</xsl:when>
</xsl:choose>
</xsl:for-each>
</body>
</xsl:template>
http://xsltransform.net/6qaFCET/2
Note: following lines can be avoided. It has been added to populate value of variables.
<xsl:copy-of select="$seg2" />
<xsl:text>
</xsl:text>
Assuming you have <AAM>value_1,value_2,value_3,value_4</AAM> and <xsl:variable name="AAM" select="//AAM"/> you can of course use e.g. <xsl:variable name="value-sequence" select="tokenize($AAM, ',')"/> and if then needed access e.g. $value-sequence[1], $value-sequence[2] and so on, thus if you know there are only four values you can declare <xsl:variable name="seq1" select="$value-sequence[1]"/>, <xsl:variable name="seq2" select="$value-sequence[2]"/> and so on. The tokenize function is part of XPath 2 and later so works with XSLT 2 or 3 processors like Saxon 9 or AltovaXML or XmlPrime.
Answering late.
Maybe this is not an exact solution. But this may help you.
This is how I'm able to split a string from an XML node into two variables using XSLT 1.0
<xsl:when test="NodeName">
<xsl:variable name="var" select="NodeName"/>
<xsl:variable name="var1" select="substring-before($var, '=')"/>
<xsl:variable name="var2" select="substring-after($var, '=')"/>
<xsl:value-of select="$var1"/>-
<xsl:value-of select="$var2"/>
</xsl:when>
For Further reference Click Here

xslt change writing-mode to FA is metadata language is FA

I'm working in the xsl-file "generate_document_structure.xsl" and a'm not so familiar with this older structure.
My goal in this is to change the writing-mode from lr-tb to rl-tb if the language in the METADATA is FA or AR.
Below a cleaned-up piece of code from the ouputfolder
<?xml version="1.0" encoding="UTF-8"?>
<fctdcl>
<publicationinfo dclselection="SelectedNode">
<props>
<attrblock type="1toN" name="language">
<attrlist>
<attrdesc id="1" name="language"/>
</attrlist>
<attrrec>
<attrval id="1">Default</attrval>
</attrrec>
</attrblock>
</props>
</publicationinfo>
It is a big guess for my how to make the connection to the METADATA if the language is FA. in other words, i'm looking for the wright xpath to the METADATA and select the value of it.
i was thinking in the way like below:
<xsl:variable name="language">
<xsl:value-of select="//*[contains(#class, ' /FCTDocuments/metadata/#language ')]/#content"></xsl:value-of>
</xsl:variable>
<xsl:choose>
<xsl:when test="$language = 'FA'">
<xsl:attribute name="writing-mode">rl-tb</xsl:attribute>
</xsl:when>
</xsl:choose>
I would appreciate it if someone could help me in this
#Toni,
I made some steps with it.
Below my current file.
<xsl:template name="FoT_page-sequence_ContentSequence">
<xsl:choose>
<xsl:when test="not(/FCTDocuments/chapter)">
<fo:page-sequence master-reference="ContentSequence">
<xsl:call-template name="AddHyphenationToSequence"/>
<xsl:call-template name="chapter_header_footer_without_config"/>
<fo:flow flow-name="xsl-region-body" xsl:use-attribute-sets="XSL_Content">
<fo:block id="last-page"/>
</fo:flow>
</fo:page-sequence>
</xsl:when>
<xsl:otherwise>
<xsl:for-each select="/FCTDocuments/chapter">
<fo:page-sequence master-reference="ContentSequence" initial-page-number="auto-odd" writing-mode="rl-tb"> <!---->
<xsl:if test="/FCTDocuments/#RSKM-ProductType = 'MM' ">
<xsl:attribute name="initial-page-number">
<xsl:text>1</xsl:text>
</xsl:attribute>
</xsl:if>
<fo:flow flow-name="xsl-region-body" xsl:use-attribute-sets="XSL_Content">
<xsl:if test="count(preceding-sibling::chapter) = 0">
<xsl:if test="$DEBUG = 'true'">
<!-- write debug informations -->
<xsl:comment>
<xsl:text>DEBUG: Starting Content creation</xsl:text>
</xsl:comment>
</xsl:if>
<fo:block>
<fo:marker marker-class-name="DOCUMENTNAME">
<xsl:value-of select="/FCTDocuments/Cover/CoverTitle"/>
</fo:marker>
<fo:marker marker-class-name="DOCUMENTINFO">
<xsl:value-of select="$DOCUMENTINFO"/>
</fo:marker>
</fo:block>
</xsl:if>
<xsl:apply-templates select="."/>
<xsl:if test="count(following-sibling::chapter) = 0">
<fo:block id="last-page"/>
</xsl:if>
</fo:flow>
</fo:page-sequence>
</xsl:for-each>
</xsl:otherwise>
</xsl:choose>
As we zoom in at the codepart below i added the attribure "writing-mode" in the fo:page-sequence. And after a test it worked fine, But this must only happend when the language is FA
So no i need to make a choose of if statement like test="/FCTDocuments/#RSKM-Language = 'FA'">
how do I manage that if the lang-attribute is FA
<fo:page-sequence master-reference="ContentSequence" initial-page-number="auto-odd" writing-mode="rl-tb"> <!---->
<xsl:if test="/FCTDocuments/#RSKM-ProductType = 'MM' ">
<xsl:attribute name="initial-page-number">
<xsl:text>1</xsl:text>
</xsl:attribute>
</xsl:if>
You initially said you were looking for the right XPath to select your METADATA/metadata, which is why I was asking to see the language code in your source XML.
I am guessing that this is what you want:
<xsl:if test="/FCTDocuments/#RSKM-Language = 'FA'">
<xsl:attribute name="writing-mode">rl</xsl:attribute>
</xsl:if>
You can then omit the writing-mode property on the fo:page-sequence since the default writing-mode value is lr-tb.

How to show page number (N of N) using xslt in PDF Report

I am using XSLT to generate PDF report. My requirements are to display page number in the format of Page N of N (e.g.Page 1 of 3) at the footer of the report. For static values it works fine and it repeats on each page. As total number of pages in the report are not known and it changes run time, so how I will accomplish this task.
My XSLT code snippet
<xsl:template name="footerall">
<xsl:variable name="maxwidth" select="7.07000" />
<fo:static-content flow-name="xsl-region-after">
<fo:block>
<xsl:variable name="tablewidth29" select="$maxwidth * 1.00000" />
<xsl:variable name="sumcolumnwidths29" select="0.04167 + 1.56250 + 0.04167" />
<xsl:variable name="factor29">
<xsl:choose>
<xsl:when
test="$sumcolumnwidths29 > 0.00000 and $sumcolumnwidths29 > $tablewidth29">
<xsl:value-of select="$tablewidth29 div $sumcolumnwidths29" />
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="1.000" />
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:variable name="defaultcolumns29" select="1" />
<xsl:variable name="defaultcolumnwidth29">
<xsl:choose>
<xsl:when test="$factor29 < 1.000">
<xsl:value-of select="0.000" />
</xsl:when>
<xsl:when test="$defaultcolumns29 > 0">
<xsl:value-of
select="($tablewidth29 - $sumcolumnwidths29) div $defaultcolumns29" />
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="0.000" />
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:variable name="columnwidth29_0" select="$defaultcolumnwidth29" />
<xsl:variable name="columnwidth29_1" select="1.56250 * $factor29" />
<fo:table width="{$tablewidth29}in" border-collapse="separate"
border-separation="0.04167in" color="black" display-align="center">
<fo:table-column column-width="{$columnwidth29_0}in" />
<fo:table-column column-width="{$columnwidth29_1}in" />
<fo:table-body>
<fo:table-row>
<fo:table-cell number-columns-spanned="2"
padding-top="0.00000in" padding-bottom="0.00000in" padding-left="0.00000in"
padding-right="0.00000in">
<fo:block padding-top="1pt" padding-bottom="1pt">
<fo:block text-align="center" space-before.optimum="-8pt">
<fo:leader leader-length="100%" leader-pattern="rule"
rule-thickness="1pt" color="black" />
</fo:block>
</fo:block>
</fo:table-cell>
</fo:table-row>
<fo:table-row>
<fo:table-cell
font-size="inherited-property-value(&apos;font-size&apos;) - 2pt"
text-align="left" padding-top="0.00000in" padding-bottom="0.00000in"
padding-left="0.00000in" padding-right="0.00000in">
<fo:block padding-top="1pt" padding-bottom="1pt">
<fo:inline font-family="Courier" font-size="10px">
<xsl:value-of select="$My XPath to varaible" />
</fo:inline>
<fo:inline font-family="Courier" font-size="10px">
<xsl:text> - </xsl:text>
<xsl:text>        </xsl:text>
<xsl:text>Page 1 of 1</xsl:text>
</fo:inline>
<fo:inline font-family="Courier" font-size="10px">
<xsl:value-of select="$My XPath to varaible" />
</fo:inline>
</fo:block>
</fo:table-cell>
<fo:table-cell
font-size="inherited-property-value(&apos;font-size&apos;) - 2pt"
text-align="right" padding-top="0.00000in" padding-bottom="0.00000in"
padding-left="0.00000in" padding-right="0.00000in">
<fo:block padding-top="1pt" padding-bottom="1pt" />
</fo:table-cell>
</fo:table-row>
</fo:table-body>
</fo:table>
</fo:block>
</fo:static-content>
</xsl:template>
I will replace the string (Page 1 of 1) by a variable but how to handle this.
Please help me.
I solved my problem by following below instructions.
Put a formatting object with an id at the end of the area. You can then do a to the labeled block that appears on the last page of the document. Here's how the markup looks:
<fo:flow flow-name="xsl-region-body">
... Lots and lots of content here
<fo:block id="TheVeryLastPage"> </fo:block>
</fo:flow>
The code creates a block with an id of TheVeryLastPage (a value that's unlikely to be used by anyone), and now you can refer to that id to get the page number of the last page of the document. Here's how the content in the area should look:
<fo:block text-align="end">
Page <fo:page-number/> of
<fo:page-number-citation
ref-id="TheVeryLastPage"/>
</fo:block>
When FOP formats this markup, it generates something like "Page 2 of 5".
My reference URL is: http://www.ibm.com/developerworks/xml/tutorials/x-xslfo2/section4.html
You should add an id attribute to your fo:page-sequence element, and then use a page-number-citation-last.
<fo:page-sequence id="my-sequence-id">
...
<xsl:text>Page </xsl:text>
<fo:page-number-citation />
<xsl:text> of </xsl:text>
<fo:page-number-citation-last page-citation-strategy="all" ref-id="my-sequence-id"/>
...
</fo:page-sequence>
See the specs: http://www.w3.org/TR/xslfo20/#fo_page-number-citation and http://www.w3.org/TR/xslfo20/#fo_page-number-citation-last