<?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>
I am using Apache's XML Graphics FOP 2.6 to create a PDF document containing at least 2 pages. There is no maximum number of pages.
The exact same header is used on every page.
Page 1 (see attached)
Needs to contain text with the total number of boxes, the total number of items included in the total number of boxes and a table with 1, 2 or 3 rows. On each row, there is a photo of the box, its name and the number of items it contains. There will be at least one box containing at least one item.
Page 2
Exists only if there are 4 or more boxes and it contains rows 4, 5, 6, 7, 8 and 9 (6 rows in total) of the table from Page 1. If there are more than 9 (= 3 + 6 X 1) boxes, there needs to be a new page that will contain the layout from Page 2, but containing the rows for boxes 10, ..., 15. This pattern will be followed until the last box.
Page 3
Will contain the photo, name and number of items of the first box. Underneath there will be a table, with a row containing the column names and at most 4 rows, corresponding to the first 4 items from the first box.
Page 4
If the first box has more than 4 items, there will be new page, called Page 4, containing only the continuation of the table, including the row with the column names. It will have 7 items in total and be followed by another page if the first box has more than 11 (= 4 + 7 X 1) items. And so on until the end of all items.
Page 5 (not attached to avoid repetition)
Will follow the same logic as Page 3, but in this case for the second box, if there is a second box. And so on until the end of all boxes.
Can anyone, please help me with an idea on how to build the layout-master-set in the XSL file for my requirements? I am not looking for the entire solution. Only for the general layout structure. The answer does not have to be too detailed or too bespoke for my needs. I can adapt it if needed.
<xsl:template match="/doc">
<xsl:variable name="Logo"><xsl:value-of select="Logo"/></xsl:variable>
...
<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format" xmlns:fox="http://xmlgraphics.apache.org/fop/extensions"
font-family="Nexus Sans Pro" font-weight="normal">
<fo:layout-master-set>
<fo:simple-page-master master-name="Boxes-A4" page-width="297mm" page-height="210mm"
margin-top="0mm" margin-bottom="0mm" margin-left="0mm" margin-right="0mm">
<fo:region-body region-name="xsl-region-body"/>
<fo:region-before region-name="xsl-region-before" extent="70mm"/>
</fo:simple-page-master>
<fo:simple-page-master master-name="Items-A4" page-width="297mm" page-height="210mm"
margin-top="0mm" margin-bottom="0mm" margin-left="0mm" margin-right="0mm">
<fo:region-body region-name="xsl-region-body"/>
<fo:region-before region-name="xsl-region-before" extent="70mm"/>
</fo:simple-page-master>
</fo:layout-master-set>
I have tried the code above (using xsl:stylesheet version="1.0"), but have failed in getting things to be laid out appropriately. The rows of the table that do not fit on a page do not get displayed on the following page, even though I mark appropriate rows with break-before="page" aka page-break-before="always".
As an aid, I can insert the indices from the backend data structure into the parameters used by the library so that I know each element's index.
Thank you very much.
Page 1
Page 2
Page 3
Page 4
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:fo="http://www.w3.org/1999/XSL/Format"
xmlns:fox="http://xmlgraphics.apache.org/fop/extensions">
<xsl:output indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/doc">
<fo:root font-family="Nexus Sans Pro" font-weight="normal">
<fo:layout-master-set>
<fo:simple-page-master master-name="Boxes-A4" page-width="297mm" page-height="210mm"
margin-top="0mm" margin-bottom="0mm" margin-left="0mm" margin-right="0mm">
<fo:region-body region-name="xsl-region-body"/>
<fo:region-before region-name="xsl-region-before" extent="70mm"/>
</fo:simple-page-master>
<fo:simple-page-master master-name="Items-A4" page-width="297mm" page-height="210mm"
margin-top="0mm" margin-bottom="0mm" margin-left="0mm" margin-right="0mm">
<fo:region-body region-name="xsl-region-body"/>
<fo:region-before region-name="xsl-region-before" extent="70mm"/>
</fo:simple-page-master>
</fo:layout-master-set>
<xsl:call-template name="boxes-template"/>
<xsl:call-template name="items-template"/>
</fo:root>
</xsl:template>
<xsl:template name="boxes-template">
<fo:page-sequence master-reference="Boxes-A4" font-family="Nexus Sans Pro" font-weight="normal">
<fo:static-content flow-name="xsl-region-before">
<fo:block-container border-bottom-width="1pt"
border-bottom-style="solid"
border-bottom-color="rgb(220,220,220)"
position="absolute" top="1mm" left="5mm" right="5mm" height="60mm">
<xsl:variable name="Logo" select="Logo"/>
<fo:block-container
background-image="url({$Logo})"
top="5mm" left="5mm" width="50mm" height="50mm"
background-repeat="no-repeat"
fox:background-image-width="50mm" fox:background-image-height="50mm"
absolute-position="absolute">
<fo:block/>
</fo:block-container>
<xsl:variable name="Stamp" select="Stamp"/>
<fo:block-container
background-image="url({$Stamp})"
top="5mm" right="5mm" width="50mm" height="50mm"
background-repeat="no-repeat"
fox:background-image-width="50mm" fox:background-image-height="50mm"
absolute-position="absolute">
<fo:block/>
</fo:block-container>
<fo:block-container position="absolute" top="8mm" left="80mm" width="120mm" height="42mm">
<fo:table table-layout="fixed" width="100%">
<fo:table-column column-width="100%"/>
<fo:table-body>
<fo:table-row>
<fo:table-cell height="12mm">
<fo:block font-family="Nexus Sans Pro Bold"
text-align="center" font-size="32pt"> Header Text
</fo:block>
</fo:table-cell>
</fo:table-row>
<fo:table-row>
<fo:table-cell display-align="after" height="10mm">
<fo:block font-family="Nexus Sans Pro"
display-align="after" text-align="center" font-size="32pt"
color="rgb(233,113,28)">
<xsl:value-of select="user"/>
</fo:block>
</fo:table-cell>
</fo:table-row>
</fo:table-body>
</fo:table>
</fo:block-container>
<fo:block-container position="absolute" top="48mm" left="77mm" width="157mm" height="10mm">
<fo:table table-layout="fixed" width="100%">
<fo:table-body>
<fo:table-row>
<fo:table-cell height="10mm">
<fo:block font-family="Nexus Sans Pro" font-weight="normal" font-size="15pt"
color="rgb(128,128,128)">
From:
<xsl:value-of select="fromDate"/>
</fo:block>
</fo:table-cell>
<fo:table-cell height="10mm">
<fo:block font-family="Nexus Sans Pro" font-weight="normal" font-size="15pt"
color="rgb(128,128,128)">
To:
<xsl:value-of select="toDate"/>
</fo:block>
</fo:table-cell>
</fo:table-row>
</fo:table-body>
</fo:table>
</fo:block-container>
</fo:block-container>
</fo:static-content>
<fo:flow flow-name="xsl-region-body">
<fo:block-container position="absolute" top="75mm" left="110mm" width="120mm" height="20mm">
<fo:table table-layout="fixed" width="100%">
<fo:table-column column-number="1" column-width="50%"/>
<fo:table-column column-number="2" column-width="50%"/>
<fo:table-body>
<fo:table-row>
<fo:table-cell height="10mm">
<fo:block
font-family="Nexus Sans Pro Bold"
font-size="15pt" color="rgb(35,31,32)">
Total number of boxes:
</fo:block>
</fo:table-cell>
<fo:table-cell height="10mm">
<fo:block font-family="Nexus Sans Pro Bold"
font-size="15pt" color="rgb(35,31,32)">
<xsl:value-of select="totalNumberOfBoxes"/>
</fo:block>
</fo:table-cell>
</fo:table-row>
<fo:table-row>
<fo:table-cell height="10mm">
<fo:block font-family="Nexus Sans Pro Bold"
font-size="15pt" color="rgb(35,31,32)">
Total number of items:
</fo:block>
</fo:table-cell>
<fo:table-cell height="10mm">
<fo:block font-family="Nexus Sans Pro Bold"
font-size="15pt" color="rgb(35,31,32)">
<xsl:value-of select="totalNumberOfItems"/>
</fo:block>
</fo:table-cell>
</fo:table-row>
</fo:table-body>
</fo:table>
</fo:block-container>
<xsl:for-each select="/doc/box">
<xsl:variable name="boxImageURL" select="boxImageURL"/>
<fo:block-container position="absolute" top="105mm" left="30mm" width="220mm" height="26mm">
<fo:table table-layout="fixed" width="100%">
<fo:table-column column-number="1" column-width="15%"/>
<fo:table-column column-number="2" column-width="70%"/>
<fo:table-column column-number="3" column-width="15%"/>
<fo:table-body>
<fo:table-row page-break-inside="auto"
border-top-width="1pt"
border-top-style="solid"
border-top-color="rgb(220,220,220)"
margin-bottom="2mm"
height="24mm">
<fo:table-cell>
<xsl:if test="$boxImageURL != 'null'">
<fo:block-container
background-image="url({$boxImageURL})"
top="110mm" right="15mm" width="15mm" height="20mm"
background-repeat="no-repeat" margin-top="2mm"
fox:background-image-width="15mm" fox:background-image-height="20mm">
<fo:block/>
</fo:block-container>
</xsl:if>
</fo:table-cell>
<fo:table-cell display-align="center" height="20mm">
<fo:block text-align="left" font-size="16pt" color="rgb(35,31,32)">
<xsl:value-of select="boxTitle"/>
</fo:block>
</fo:table-cell>
<fo:table-cell display-align="center" height="20mm">
<fo:block text-align="left" font-size="16pt" color="rgb(35,31,32)">
<xsl:value-of select="numberOfItems"/>
</fo:block>
</fo:table-cell>
</fo:table-row>
</fo:table-body>
</fo:table>
</fo:block-container>
</xsl:for-each>
</fo:flow>
</fo:page-sequence>
</xsl:template>
<xsl:template name="items-template">
<xsl:variable name="Logo"><xsl:value-of select="Logo"/></xsl:variable>
<xsl:variable name="Stamp"><xsl:value-of select="Stamp"/></xsl:variable>
<xsl:variable name="user"><xsl:value-of select="user"/></xsl:variable>
<xsl:variable name="fromDate"><xsl:value-of select="fromDate"/></xsl:variable>
<xsl:variable name="toDate"><xsl:value-of select="toDate"/></xsl:variable>
<xsl:for-each select="/doc/box">
<xsl:variable name="boxImageURL" select="boxImageURL"/>
<fo:page-sequence master-reference="Items-A4" font-family="Nexus Sans Pro" font-weight="normal">
<fo:static-content flow-name="xsl-region-before">
... Same header as on the Box-A4
</fo:static-content>
<fo:flow flow-name="xsl-region-body">
<fo:block-container page-break-before="always"
position="absolute" top="70mm" left="30mm" width="220mm" height="24mm">
<fo:table page-break-before="always" table-layout="fixed" width="100%">
<fo:table-column column-number="1" column-width="15%"/>
<fo:table-column column-number="2" column-width="85%"/>
<fo:table-body>
<fo:table-row margin-bottom="2mm"
height="22mm">
<fo:table-cell>
<xsl:if test="$boxImageURL != 'null'">
<fo:block-container
background-image="url({$boxImageURL})"
top="110mm" right="15mm" width="15mm" height="20mm"
background-repeat="no-repeat" margin-top="2mm"
fox:background-image-width="15mm" fox:background-image-height="20mm">
<fo:block/>
</fo:block-container>
</xsl:if>
</fo:table-cell>
<fo:table-cell display-align="center" height="20mm">
<fo:block margin-top="4mm" text-align="left" font-size="16pt" color="rgb(35,31,32)">
<xsl:value-of select="boxTitle"/>
<fo:block margin-top="4mm" text-align="left" font-size="16pt" color="rgb(35,31,32)">
<xsl:value-of select="numberOfThings"/> things
</fo:block>
</fo:block>
</fo:table-cell>
</fo:table-row>
</fo:table-body>
</fo:table>
</fo:block-container>
<fo:block-container position="absolute" top="100mm" left="30mm" width="220mm" height="24mm">
<fo:table page-break-before="always" table-layout="fixed" width="100%">
<fo:table-column column-number="1" column-width="60%"/>
<fo:table-column column-number="2" column-width="15%"/>
<fo:table-column column-number="3" column-width="25%"/>
<fo:table-body>
<fo:table-row border-top-width="1pt"
border-top-style="solid"
border-top-color="rgb(220,220,220)"
margin-bottom="2mm"
height="22mm">
<fo:table-cell display-align="center" height="20mm">
<fo:block text-align="left" font-size="16pt" color="rgb(35,31,32)">
Item title
</fo:block>
</fo:table-cell>
<fo:table-cell display-align="center" height="20mm">
<fo:block text-align="left" font-size="16pt" color="rgb(35,31,32)">
Revision
</fo:block>
</fo:table-cell>
<fo:table-cell display-align="center" height="20mm">
<fo:block text-align="left" font-size="16pt" color="rgb(35,31,32)">
Date completed
</fo:block>
</fo:table-cell>
</fo:table-row>
</fo:table-body>
</fo:table>
</fo:block-container>
<fo:block-container position="absolute" top="125mm" left="30mm" width="220mm" height="24mm">
<fo:table page-break-before="always" table-layout="fixed" width="100%">
<fo:table-column column-number="1" column-width="60%"/>
<fo:table-column column-number="2" column-width="15%"/>
<fo:table-column column-number="3" column-width="25%"/>
<fo:table-body>
<xsl:for-each select="items/item">
<fo:table-row keep-together.within-page="always"
break-after="page"
border-top-width="1pt"
border-top-style="solid"
border-top-color="rgb(220,220,220)"
margin-bottom="2mm"
height="22mm">
<fo:table-cell display-align="center" height="20mm">
<fo:block text-align="left" font-size="16pt" color="rgb(35,31,32)">
<xsl:value-of select="itemTitle"/>
</fo:block>
</fo:table-cell>
<fo:table-cell display-align="center" height="20mm">
<fo:block text-align="left" font-size="16pt" color="rgb(35,31,32)">
<xsl:value-of select="revision"/>
</fo:block>
</fo:table-cell>
<fo:table-cell display-align="center" height="20mm">
<fo:block text-align="left" font-size="16pt" color="rgb(35,31,32)">
<xsl:value-of select="dateCompleted"/>
</fo:block>
</fo:table-cell>
</fo:table-row>
</xsl:for-each>
</fo:table-body>
</fo:table>
</fo:block-container>
</fo:flow>
</fo:page-sequence>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
My simplified parameters.xml (lacking a few lines):
<doc>
<Logo>ELogo.jpg</Logo>
<Stamp>Stamp.jpg</Stamp>
<backgroundImageURL>bkg.jpg</backgroundImageURL>
<user>John Richard Edgar Bowens-Robins III</user>
<fromDate>1st March 2021</fromDate>
<toDate>31 November 2021</toDate>
<totalNumberOfBoxes>5</totalNumberOfBoxes>
<totalNumberOfItems>19</totalNumberOfItems>
<box>
<boxImageURL>box1.jpg</boxImageURL>
<boxTitle>JREBR's Box 1</boxTitle>
<items>
<item>
<itemTitle>The Nice Item 11</itemTitle>
</item>
<item>
<itemTitle>The Nice Item 12</itemTitle>
</item>
<item>
<itemTitle>The Nice Item 13</itemTitle>
</item>
</items>
</box>
<box>
<boxImageURL>box2.jpg</boxImageURL>
<boxTitle>JREBR's Box 2</boxTitle>
<items>
<item>
<itemTitle>The Nice Item 21</itemTitle>
</item>
<item>
<itemTitle>The Nice Item 22</itemTitle>
</item>
<item>
<itemTitle>The Nice Item 23</itemTitle>
</item>
</items>
</box>
</doc>
What you really call "Page 1", "Page 2" ... you really mean this:
Section 1 which is all the boxes. This could be 1 to x pages depending on the quantity of boxes. All the page templates are the same so this is one page sequence with one page master.
Section 2 to n which is a page sequence for each box listing all the items. All of these page sequences are the same (one simple page master).
You do not explain what photo 1 and photo 2 are in the header for these but I would assume they are the same for every page. If that is not true and are different for "boxes" and "items" then possibly you may have different headers.
So you only have two simple-page-masters one called "boxes" and one called "items". You would just create the "boxes" page-sequence referencing the simple-page-master for boxes. You do not present a sample XML, so let's just say it looks like this for simplicity:
<order>
<box>
<name>Box 1</name>
<items>
<item>Item 1:1</item>
<item>Item 1:2</item>
<item>Item 1:3</item>
</items>
</box>
<box>
<name>Box 2</name>
<items>
<item>Item 2:1</item>
<item>Item 2:2</item>
<item>Item 2:3</item>
</items>
</box>
<box>
<name>Box 3</name>
<items>
<item>Item 3:1</item>
<item>Item 3:2</item>
<item>Item 3:3</item>
</items>
</box>
</order>
Then this simple XSL would throw pages for boxes and items in those boxes:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:fo="http://www.w3.org/1999/XSL/Format">
<xsl:template match="/">
<fo:root>
<fo:layout-master-set>
<fo:simple-page-master master-name="boxes" page-width="7in" page-height="4in">
<fo:region-body region-name="body" margin-top="0.5in" margin-bottom="0.5in" margin-left="0.5in" margin-right="0.5in"/>
</fo:simple-page-master>
<fo:simple-page-master master-name="items" page-width="7n" page-height="4in">
<fo:region-body region-name="body" margin-top="0.5in" margin-bottom="0.5in" margin-left="0.5in" margin-right="0.5in"/>
</fo:simple-page-master>
</fo:layout-master-set>
<xsl:call-template name="boxes"/>
<xsl:call-template name="items"/>
</fo:root>
</xsl:template>
<xsl:template name="boxes">
<fo:page-sequence master-reference="boxes">
<fo:flow flow-name="body">
<!-- Output the table of boxes -->
<xsl:for-each select="/order/box">
<fo:block>
<xsl:value-of select="name"/>
</fo:block>
</xsl:for-each>
</fo:flow>
</fo:page-sequence>
</xsl:template>
<xsl:template name="items">
<xsl:for-each select="/order/box">
<fo:page-sequence master-reference="items">
<fo:flow flow-name="body">
<xsl:for-each select="items/item">
<fo:block>
<xsl:value-of select="."/>
</fo:block>
</xsl:for-each>
</fo:flow>
</fo:page-sequence>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
This results in:
Combining this with #Tony Graham's suggestion on doing the tables and you have the whole layout. If you wonder how that works with automatic page flows, here is the exact example above with a few more boxes and one box (Box 4) with more items ... I only changed the fo:block font-size to cause pagination.
Use fo:table, and for each fo:table-row specify height (https://www.w3.org/TR/xsl11/#height) with a suitable value that will get you the required number of rows per page.
You may also need to specify keep-together.within-page="always" to avoid breaking a table row. FOP may or may not support that on fo:table-row (or fo:table-cell).
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 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.
For the following xml file, i need to generate an xsl-fo file to be converted into pdf.
I am new to style sheets and struggling to create dynamic table. Please help.
Also, the width for each column varies,based on the column.How would i include this into the code?
The Column Headers and Column Values are dynamically populated in the xml file. Below is a sample.
Can anybody please help in generating xsl-fo or xslt code?
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ReportData>
<ColumnHeaders>
<ColumnHeader>
<Name>Col-Header1</Name>
<Width>5</Length>
</ColumnHeader>
<ColumnHeader>
<Name>Col-Header2</Name>
<Width>10</Length>
</ColumnHeader>
<ColumnHeader>
<Name>Col-Header3</Name>
<Width>8</Length>
</ColumnHeader>
</ColumnHeaders>
<Rows>
<Row>
<Column>Row1-Col1</Column>
<Column>Row1-Col2</Column>
<Column>Row1-Col3</Column>
</Row>
<Row>
<Column>Row2-Col1</Column>
<Column>Row2-Col2</Column>
<Column>Row2-Col3</Column>
</Row>
</Rows>
</ReportData>
This should get you started. I used cm for the column width and the page is 11" x 8.5" (landscape) so the table would fit on the page. This should be easy for you to change.
XML Input (fixed to be well-formed)
<ReportData>
<ColumnHeaders>
<ColumnHeader>
<Name>Col-Header1</Name>
<Width>5</Width>
</ColumnHeader>
<ColumnHeader>
<Name>Col-Header2</Name>
<Width>10</Width>
</ColumnHeader>
<ColumnHeader>
<Name>Col-Header3</Name>
<Width>8</Width>
</ColumnHeader>
</ColumnHeaders>
<Rows>
<Row>
<Column>Row1-Col1</Column>
<Column>Row1-Col2</Column>
<Column>Row1-Col3</Column>
</Row>
<Row>
<Column>Row2-Col1</Column>
<Column>Row2-Col2</Column>
<Column>Row2-Col3</Column>
</Row>
</Rows>
</ReportData>
XSLT 1.0
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format">
<xsl:output indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/">
<fo:root>
<fo:layout-master-set>
<fo:simple-page-master master-name="my-page" page-height="8.5in" page-width="11in">
<fo:region-body margin="1in" margin-top="1.5in" margin-bottom="1.5in"/>
</fo:simple-page-master>
</fo:layout-master-set>
<fo:page-sequence master-reference="my-page">
<fo:flow flow-name="xsl-region-body">
<xsl:apply-templates/>
</fo:flow>
</fo:page-sequence>
</fo:root>
</xsl:template>
<xsl:template match="ReportData">
<fo:table>
<fo:table-header>
<fo:table-row>
<xsl:apply-templates select="ColumnHeaders/ColumnHeader"/>
</fo:table-row>
</fo:table-header>
<fo:table-body>
<xsl:apply-templates select="Rows/Row"/>
</fo:table-body>
</fo:table>
</xsl:template>
<xsl:template match="ColumnHeader">
<fo:table-cell width="{Width}cm" border="solid black 1px" padding="2px" font-weight="bold" text-align="center">
<fo:block><xsl:value-of select="Name"/></fo:block>
</fo:table-cell>
</xsl:template>
<xsl:template match="Row">
<fo:table-row>
<xsl:apply-templates/>
</fo:table-row>
</xsl:template>
<xsl:template match="Column">
<fo:table-cell border="solid black 1px" padding="2px">
<fo:block><xsl:value-of select="."/></fo:block>
</fo:table-cell>
</xsl:template>
</xsl:stylesheet>
XSL-FO Output
<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
<fo:layout-master-set>
<fo:simple-page-master master-name="my-page" page-height="8.5in" page-width="11in">
<fo:region-body margin="1in" margin-top="1.5in" margin-bottom="1.5in"/>
</fo:simple-page-master>
</fo:layout-master-set>
<fo:page-sequence master-reference="my-page">
<fo:flow flow-name="xsl-region-body">
<fo:table>
<fo:table-header>
<fo:table-row>
<fo:table-cell width="5cm"
border="solid black 1px"
padding="2px"
font-weight="bold"
text-align="center">
<fo:block>Col-Header1</fo:block>
</fo:table-cell>
<fo:table-cell width="10cm"
border="solid black 1px"
padding="2px"
font-weight="bold"
text-align="center">
<fo:block>Col-Header2</fo:block>
</fo:table-cell>
<fo:table-cell width="8cm"
border="solid black 1px"
padding="2px"
font-weight="bold"
text-align="center">
<fo:block>Col-Header3</fo:block>
</fo:table-cell>
</fo:table-row>
</fo:table-header>
<fo:table-body>
<fo:table-row>
<fo:table-cell border="solid black 1px" padding="2px">
<fo:block>Row1-Col1</fo:block>
</fo:table-cell>
<fo:table-cell border="solid black 1px" padding="2px">
<fo:block>Row1-Col2</fo:block>
</fo:table-cell>
<fo:table-cell border="solid black 1px" padding="2px">
<fo:block>Row1-Col3</fo:block>
</fo:table-cell>
</fo:table-row>
<fo:table-row>
<fo:table-cell border="solid black 1px" padding="2px">
<fo:block>Row2-Col1</fo:block>
</fo:table-cell>
<fo:table-cell border="solid black 1px" padding="2px">
<fo:block>Row2-Col2</fo:block>
</fo:table-cell>
<fo:table-cell border="solid black 1px" padding="2px">
<fo:block>Row2-Col3</fo:block>
</fo:table-cell>
</fo:table-row>
</fo:table-body>
</fo:table>
</fo:flow>
</fo:page-sequence>
</fo:root>
PDF Output