I have a chunk of XSL code (along with Apache fop), that i want to reuse:
XSL version and schema used
<xsl:stylesheet version="3.0" xml:lang="en"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:fo="http://www.w3.org/1999/XSL/Format"
xmlns:exsl="http://exslt.org/common"
xmlns:java="http://xml.apache.org/xslt/java"
exclude-result-prefixes="java"
xmlns:map="xalan://java.util.HashMap" extension-element-prefixes="map">
Chunk to reuse:
<xsl:choose>
<xsl:when test="map:get($etiquetas,'datosMensajeLabel')" />
<fo:table-cell padding="2pt" border-top-color="black"
border-top-width="0.5pt" border-top-style="solid"
background-color="grey">
<fo:block text-align="start" color="white" font-size="12pt">
<xsl:value-of
select="map:put($etiquetas,'datosMensajeLabel','')" />
<xsl:value-of
select="map:get($etiquetas,'datosMensajeLabel')" />
</fo:block>
</fo:table-cell>
</xsl:choose>
<xsl:otherwhise>
<fo:table-cell padding="2pt" background-color="grey">
<fo:block text-align="start" color="white" font-size="12pt">
<xsl:value-of
select="map:get($etiquetas,'datosMensajeLabel')" />
</fo:block>
</fo:table-cell>
</xsl:otherwhise>
I tried so far:
Declare and use named templates: it fails since table-cell breaks the Apache fop schema where template is declared
Put that chunk of code in another file and use import or include: it's of no use as it's not used as a child of xsl:stylesheet
The reason you are getting the error fo:table-cell not allowed in that position is that the preceding xsl:when element is closed and therefore not wrapping the <fo:table-cell> element.
xsl:choose only allows either xsl:when or xsl:otherwise as direct children and thus complains when it finds <fo:table-cell>.
Wrapping xsl:when around <fo:table-cell> should eliminate the error message.
By the way, you have misspelt xsl:otherwise
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 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 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.
I am generating a PDF using XSL-FO and XML. In a textbox, the user can enter data like "1", then he presses ENTER, then "2", ENTER, "3", etc. But in the XML and hence in the PDF, the output is "1234567". How can I preserve the line breaks? I already tried white-space-collapse, linefeed-treatment and white-space-treatment but that didn't help.
My XSL looks like:
<xsl:template match="AddCmt">
<fo:block keep-together="always"> Additional Comments
<fo:block-container border-style="solid" height="20mm" width="170mm" space-after="5mm">
<fo:block>
<xsl:attribute name="id">
<xsl:value-of select="../CMT_ID"/>
</xsl:attribute>
<xsl:value-of select="../ANS_CMT"/>
</fo:block>
</fo:block-container>
</fo:block>
</xsl:template>
When I enter the following:
hello
medhavi
saraswat
This is the XML I get:
<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type='text/xsl' href='e:\tmm-09.3\src\pmod\WorkOrder.xsl'?>
<Root>
<WorkOrders>
<Detail>Id="ANS_436_FLD_1" Label="qq">qq</Detail>
<Ans Checked="0" Id="ANS_436_FLD_2" Label="ww">ww</Ans>
<ID>ANS_436_FLD</ID>
<ANS_FLD>0|0</ANS_FLD>
<CMT_ID>ANS_436_CMT</CMT_ID>
<ANS_CMT>hello medhavi saraswat</ANS_CMT>
<Warning>
<Line>warning 11</Line>
<Line>22</Line>
<Line>33</Line>
<Line>44</Line>
<Line></Line>
<Line>66</Line>
<Line>77</Line>
<Line></Line>
</Warning>
It should work with the following xml (you should add all the attributes):
<xsl:template match="AddCmt">
<fo:block keep-together="always"> Additional Comments
<fo:block-container border-style="solid" height="20mm" width="170mm" space-after="5mm">
<fo:block wrap-option="wrap" linefeed-treatment="preserve" white-space-collapse="false" white-space-treatment="preserve">
<xsl:attribute name="id">
<xsl:value-of select="../CMT_ID"/>
</xsl:attribute>
<xsl:value-of select="../ANS_CMT"/>
</fo:block>
</fo:block-container>
</fo:block>
</xsl:template>
But as I mentioned in the comments, if your XML already has no linebreaks, there's no way your PDF will. You mentioned in your question there are no linebreaks in your XML, hence no linebreaks in the PDF.
Try checking out why there are no linebreaks in the XML. If you can provide any more information (a piece of your XML, the code you use to construct the XML, ...), please edit your answer and add the information.