I am working on a project in which we have charts and a table exported to PDF. We are using Apache FOP for the PDF generation. The charts are in SVG and display fine if there's only one. However, we will have cases in which there are up to four, and in these instances only three of the four are fitting on the generated PDF. I need all images to fit regardless of number. I'm afraid simply putting the page in landscape will be a temporary solution for when we need even more to fit. The sizes of each chart are set in pixels from the svg generated in the client by the Highcharts library. It appears as though the images are inserted into the pdf without any scaling, even though I set attributes for the instream-foreign-object per an example seen here: Scaling images using scale-to-fit
So I need each chart to "shrink to fit". I have tried setting the length and width of the element that encloses each element that contains an instream-foreign object (I am also including my xsl). Within the instream-foreign -object I am assigning the svg width & height to the values from the actual chart svg. I thought maybe this was the problem, but if I don't include these dimensions the charts don't appear in the pdf. I also tried setting the scaling attribute to "non-uniform" per the question here: Scale images with fixed height and the results were no better. It actually stretched a chart across the whole page thus displaying only one of four. Here's my xsl:
<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 method="xml" indent="yes"/>
<xsl:template match="/">
<fo:root>
<fo:layout-master-set>
<fo:simple-page-master master-name="exportPage">
<fo:region-body />
</fo:simple-page-master>
</fo:layout-master-set>
<fo:page-sequence master-reference="exportPage">
<fo:flow flow-name="xsl-region-body">
<fo:block id="mainTitleBlock" font-family="arial, helvetica, sans-serif" color="#5c068c" font-weight="bold">
<xsl:value-of select="exports/export/charts/#mainTitle"/>
</fo:block>
<fo:block id="timestampBlock" font-family="arial, helvetica, sans-serif" font-size="small" color="#6D869F">
<xsl:value-of select="exports/export/charts/#timeStamp"/>
</fo:block>
<!-- This is where the charts go -->
<!-- Within this block will be an inline element for each chart-->
<fo:block id="chartBlock" width="8.25in" height="6in">
<xsl:apply-templates select="exports/export/charts/chart"/>
</fo:block>
<fo:block id="tableBlock" >
<xsl:apply-templates select="exports/export/table"/>
</fo:block>
</fo:flow>
</fo:page-sequence>
</fo:root>
</xsl:template>
<!-- Creates the table -->
<xsl:template match="table">
<fo:table table-layout="fixed" width="100%" >
<fo:table-header>
<fo:table-row>
<xsl:apply-templates select="tblRow[position() = 1]"/>
</fo:table-row>
</fo:table-header>
<fo:table-body>
<xsl:apply-templates select="tblRow[position() > 1]"/>
</fo:table-body>
</fo:table>
</xsl:template>
<xsl:template match="hdrCell">
<fo:table-cell background-color="#666" border-right-style="solid" border-right-width="1px" border-right-color="white" empty-cells="show">
<fo:block color="white" font-family="arial, helvetica, sans-serif" font-size="x-small"><xsl:value-of select="."/></fo:block>
</fo:table-cell>
</xsl:template>
<xsl:template match="tblCell">
<fo:table-cell border-bottom-style="solid" border-bottom-width="1px" border-bottom-color="#E3E3E3" >
<fo:block color="#7E7E7E" font-family="arial, helvetica, sans-serif" font-size="x-small"><xsl:value-of select="."/></fo:block>
</fo:table-cell>
</xsl:template >
<xsl:template match="tblRow[position() > 1]">
<fo:table-row>
<xsl:apply-templates />
</fo:table-row>
</xsl:template>
<xsl:template match="chart">
<fo:inline>
<fo:instream-foreign-object xmlns:svg="http://www.w3.org/2000/svg" content-width="scale-to-fit" content-height="100%" width="100%" scaling="uniform">
<svg:svg width="{svg:svg/#width}" height="{svg:svg/#height}">
<xsl:copy-of select="svg:svg"/>
</svg:svg>
</fo:instream-foreign-object>
</fo:inline>
</xsl:template>
</xsl:stylesheet>
What am I missing? Would it help to display the charts in table-cells (thus breaking the convention of not using tables for layout- the horror!)? How can I get these to scale and fit in the page?
Thanks,
Brandt
The scale property makes the chart fit in the containing block. If you haven't set dimensions for that block, the formatting engine won't know what size to scale to so it will use 100%.
I don't know what happens when you place more than one chart into one block.
You may need to put the charts in a table, one chart per column so you can set the column widths depending on the number of charts.
Related
I have a text written on a certificate document which is an image, but I am trying to write the text diagonally on the image. I am unable to change it even after changing the reference orientation of the container within which the text is present.
<xsl:template match="graphicBack">
<fo:block absolute-position="absolute">
<fo:block-container position="absolute">
<fo:external-graphic xmlns:fo="http://www.w3.org/1999/XSL/Format" scaling="uniform" content-width="210mm" content-height="296.99mm">
<xsl:attribute name="src" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:value-of select="var" />
</xsl:attribute>
</fo:external-graphic>
</fo:block-container>
<fo:block-container absolute-position="absolute" left="20mm" top="200mm">
<fo:block color="#CC6133" font-family="Courier" font-style="normal" display-align="center" font-size="300px">
COPY
</fo:block>
</fo:block-container>
</fo:block>
</xsl:template>
If you are using AH Formatter, then you can use axf:transform and axf:transform-origin (see https://www.antennahouse.com/product/ahf66/ahf-ext.html#transformation) to rotate the block to an arbitrary angle.
See the 'Block transformation' example in the "Comprehensive XSL-FO Tutorials and Samples Collection" at https://www.antennahouse.com/comprehensive-xsl-fo-tutorials-and-samples-collection/.
I have created index page using XSLT code. The contents name are shown to index page correctly but i want to map contents according to page number for specific title.
I am getting title with their description So I have named that block as id="TOC" and given as ref-id=”TOC” but the page number is not reflecting in my title.
Title:- Title names present in Index page.
Summary:- Title content associated with page.
The below is my XSLT-2.0 sample code:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="content_name">
<fo:block space-after="7pt" space-after.conditionality="retain" line-height="1.147" font-family="Calibri" font-size="15pt" font-weight="bold" language="FR">
<fo:inline>
<fo:leader leader-length="0pt" />
<xsl:value-of select="title"/>
<fo:page-number-citation ref-id="TOC"/>
</fo:inline>
</fo:block>
</xsl:template>
<xsl:template match="pro_list">
<fo:block space-after="15pt" space-after.conditionality="retain" line-height="1.147" font-family="Calibri" font-size="15pt" font-weight="bold" text-decoration="underline" language="FR">
<fo:inline>
<fo:leader leader-length="0pt" />
<xsl:value-of select="title" id="TOC"/>
</fo:inline>
</fo:block>
<fo:block space-after="8pt" space-after.conditionality="retain" line-height="1.147" font-family="Calibri" font-size="15pt" language="FR">
<fo:inline>
<fo:leader leader-length="0pt"/>
<xsl:value-of select="summary" disable-output-escaping="yes" />
</fo:inline>
</fo:block>
</xsl:template>
</xsl:stylesheet>
This is the output:
Contents
Title1 page no.
Title2 page no.
Title3 page no.
Suppose title1 content is associated with page2 & similar for title2-3 & title3-4, then output looks like as follows
Contents
Title1 2
Tilte2 3
Title3 4
Is there any syntax or predefined function available to do index mapping?
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 can I put a fo:block with a text like:
<fo:block text-align="right" font-size="48pt">
HALLO
</fo:block>
side by side / next to a my fo:table in the xsl file.
My XSL File looks so:
<?xml version="1.0" encoding="iso-8859-1"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format"
xmlns:java="http://xml.apache.org/xslt/java" xmlns:date="java.util.Date" xmlns:sf="java.text.SimpleDateFormat"
exclude-result-prefixes="java" version="1.0">
....
....
...
<xsl:template match="Order">
<fo:table border="0.5pt solid">
<fo:table-column column-width="5cm"/>
<fo:table-body>
<fo:table-row>
<fo:table-cell>
<fo:block font-size="10pt">
delivery:
</fo:block>
</fo:table-cell>
<fo:table-cell>
<fo:block font-weight="bold" font-size="12pt">
<xsl:value-of select="#DeliveryTime"/>
</fo:block>
</fo:table-cell>
</fo:table-row>
</fo:table-body>
</fo:table>
</xsl:stylesheet>
Next to the table above in my xsl sheet I want to put the HALLO text.
If you really want this, you can specify a block-container that contains two block-containers with absolute positions placed side by side. The table goes in one, the text goes in the other.
But it's probably simpler to extend the table across the full page width and place the 'Hallo' text inside a cell, and span/merge cells if you need more room.
I am creating an xsl fo table that will have a varying number of columns. The application uses Apache FOP to display the transformed document. When there is a low number of columns, everything displays fine (i.e. content of the cells is centered and displayed in full although some columns end up taking up two lines because the text wraps). However, some tables have over 12 columns, and this is where the problem occurs: in the column header cells, the name of the column is all the way to the right of the cell taking multiple lines. It looks like the words are wrapping, but even the last two characters are seemingly cut off. The text is not leaking into the neighboring cells.
Here is the input xml file in this case it's a row for the table header and one row for the body for brevity's sake. I didn't include the chart elements referenced in the xsl document as that part displays properly:
<exports>
<export>
<table>
<tblRow>
<hdrCell>Month</hdrCell>
<hdrCell>Allow Amt PEPM Med</hdrCell>
<hdrCell>Allow Amt PEPM Rx</hdrCell>
<hdrCell>Allow Amt PEPM Med and Rx</hdrCell>
<hdrCell>Allow Amt PMPM Med</hdrCell>
<hdrCell>Allow Amt PMPM Rx</hdrCell>
<hdrCell>Allow Amt PMPM Med and Rx</hdrCell>
<hdrCell>Employees Avg Med or Rx</hdrCell>
<hdrCell>Members Avg Med or Rx</hdrCell>
<hdrCell>Net Pay PEPM Med</hdrCell>
<hdrCell>Net Pay PEPM Rx</hdrCell>
<hdrCell>Net Pay PEPM Med and Rx</hdrCell>
<hdrCell>Net Pay PMPM Med</hdrCell>
<hdrCell>Net Pay PMPM Rx</hdrCell>
<hdrCell>Net Pay PMPM Med and Rx</hdrCell>
</tblRow>
<tblRow>
<tblCell>Jan 2010</tblCell>
<tblCell>11</tblCell>
<tblCell>202</tblCell>
<tblCell>213</tblCell>
<tblCell>26</tblCell>
<tblCell>30</tblCell>
<tblCell>56</tblCell>
<tblCell>56</tblCell>
<tblCell>44</tblCell>
<tblCell>11</tblCell>
<tblCell>22</tblCell>
<tblCell>33</tblCell>
<tblCell>12</tblCell>
<tblCell>12</tblCell>
<tblCell>24</tblCell>
<tblCell>1</tblCell>
</tblRow>
</table>
</export>
And here is the xsl file that transforms the input file to xsl fo. I am new to xsl.
<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 method="xml" indent="yes"/>
<xsl:template match="/">
<fo:root>
<fo:layout-master-set>
<fo:simple-page-master master-name="exportPage">
<fo:region-body />
</fo:simple-page-master>
</fo:layout-master-set>
<fo:page-sequence master-reference="exportPage">
<fo:flow flow-name="xsl-region-body">
<fo:block id="chartBlock">
<!-- THIS PART WORKS FINE -->
</fo:block>
<!-- THE PROBLEM PART -->
<fo:block id="tableBlock" margin="0.25in">
<xsl:apply-templates select="exports/export/table"/>
</fo:block>
</fo:flow>
</fo:page-sequence>
</fo:root>
</xsl:template>
<!-- Creates the table -->
<xsl:template match="table">
<fo:table table-layout="fixed" width="100%" >
<fo:table-header>
<fo:table-row>
<xsl:apply-templates select="tblRow[position() = 1]"/>
</fo:table-row>
</fo:table-header>
<fo:table-body>
<xsl:apply-templates select="tblRow[position() > 1]"/>
</fo:table-body>
</fo:table>
</xsl:template>
<xsl:template match="hdrCell">
<fo:table-cell background-color="#666" border-right-style="solid" border-right-width="1px" border-right-color="white" empty-cells="show">
<fo:block color="white" font-family="arial, helvetica, sans-serif" font-size="xx-small"><xsl:value-of select="."/></fo:block>
</fo:table-cell>
</xsl:template>
<xsl:template match="tblCell">
<fo:table-cell border-bottom-style="solid" border-bottom-width="1px"
border-bottom-color="#E3E3E3">
<fo:block color="#7E7E7E" font-family="arial, helvetica, sans-serif" font- size="xx-small"><xsl:value-of select="."/></fo:block>
</fo:table-cell>
</xsl:template >
<xsl:template match="tblRow[position() > 1]">
<fo:table-row>
<xsl:apply-templates />
</fo:table-row>
</xsl:template>
</xsl:stylesheet>
I have tried setting a padding right property for each table-cell's block element hoping it would shift the text to the left to no avail. I have tried adjusting the 'width' property of each block element that is a child of a table-cell. I am new to xsl in general, so I'm not sure how to proceed. Would it be helpful to specify elements with a specific width? What can I do to ensure the full width of the table is displayed in the pdf and is without this jumbled, truncated cell content? Also, all units are in 'px' where not specified.
Thanks in advance,
Brandt
Answer: removing the margin="0.25in" from the surrounding block yields the result I think you expect (except of course for the margin on that block). To be clear, change this:
<fo:block id="tableBlock" margin="0.25in">
<xsl:apply-templates select="exports/export/table"/>
</fo:block>
And remove the margin="0.25in".
Note: This is not the result you would get from a different formatter. I used RenderX on your original file and you get what you expect and the correct result. I used FOP and get the incorrect result but remove that indent (which is obviously being inherited someway improperly to only one dimension of table cells).
One additional note: You have 15 header cells and 16 cells in your sample.