I would like to generate a PDF from an image, using Apache FOP and XSLT. However, if image s bigger, then PDF document page, then it only gets as much space as it is available on the page (including right and bottom margin). So, part of the image is out of page bounds.
Is this possible to setup fop so that if image can't be fitted into the page it is automatically splitted into the multiple pages?
Here is my xslt template:
<?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"
xmlns:java="http://xml.apache.org/xslt/java"
xmlns:dp="http://www.dpawson.co.uk"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:f="Functions"
xmlns:xdt="http://www.w3.org/2005/02/xpath-datatypes"
exclude-result-prefixes="java">
<xsl:output method="xml" version="1.0" omit-xml-declaration="no" indent="yes" />
<xsl:param name="image-print-path" />
<xsl:template match="/">
<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
<fo:layout-master-set>
<fo:simple-page-master master-name="simpleA4"
page-height="29.7cm" page-width="21cm" margin-top="2cm"
margin-bottom="2cm" margin-left="2cm" margin-right="2cm">
<fo:region-body margin-top="20pt" margin-bottom="35pt" />
<fo:region-before extent=".5in"/>
<fo:region-after extent=".5in"/>
</fo:simple-page-master>
</fo:layout-master-set>
<fo:page-sequence master-reference="simpleA4">
<fo:static-content flow-name="xsl-region-before" text-align="left">
<fo:block font-size="10pt">
Print
</fo:block>
</fo:static-content>
<fo:static-content flow-name="xsl-region-after">
<fo:block font-size="10pt" text-align="left">
something else
</fo:block>
<!-- TODO: add current date, page number -->
</fo:static-content>
<fo:flow flow-name="xsl-region-body">
<fo:block font-size="10pt" page-break-after="always">
<fo:external-graphic src="{$image-print-path}"/>
</fo:block>
</fo:flow>
</fo:page-sequence>
</fo:root>
</xsl:template>
</xsl:stylesheet>
Doesn't look like there's anything in the spec that can format in the way you need. This leaves you with a few options:
check the graphic before you inject it into your XSL workflow and cut it up into a number of images to use across multiple pages
inspect the graphic to determine it's dimensions and create a page size big enough to contain it, and leave the slicing to printers
set content-width to scale-down-to-fit to show the entire graphic on a single page
Related
I have an XML that is being converted to PDF via Apache FOP, embedded in a Java program, and XSLT. This XML contains several lists of items; these lists are in the XML in a format like this:
<NameOfList>
<Listitem>
<ListItemAttributeOne/>
<ListItemAttributeTwo/>
</ListItem>
<ListItem>
<ListItemAttributeOne/>
<ListItemAttributeTwo/>
</ListItem>
<...more ListItems>
</NameOfList>
I do not know ahead of time how many ListItems there are, and I need to print their information in a PDF file like this:
(1) List Item Attribute One:
List Item Attribute Two:
(2) List Item Attribute One:
List Item Attribute Two:
(...)
(n) List Item Attribute One:
List Item Attribute Two:
I'm usually a Java developer, so I know how to do this with Java: take the list of ListItem objects, store them in an ArrayList of custom type "ListItem," and cycle through the ArrayList and print out their associated attributes, incrementing the label (1, 2, etc.) with each new item.
Is there a similar way to do this using XSLT 2.0? Can you read a list from XML into an array and print it out one item at a time in a dynamically generated list?
This is an XSLT 1.0 (you don't even need the features introduced with XSLT 2.0) that transform your input in an XSL-FO list:
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 method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/">
<fo:root>
<fo:layout-master-set>
<fo:simple-page-master master-name="simple" margin="0.5in">
<fo:region-body/>
</fo:simple-page-master>
</fo:layout-master-set>
<fo:page-sequence master-reference="simple">
<fo:flow flow-name="xsl-region-body">
<xsl:apply-templates/>
</fo:flow>
</fo:page-sequence>
</fo:root>
</xsl:template>
<xsl:template match="NameOfList">
<fo:list-block provisional-distance-between-starts="2cm" provisional-label-separation="2mm">
<xsl:apply-templates select="*"/>
</fo:list-block>
</xsl:template>
<xsl:template match="ListItem">
<fo:list-item>
<fo:list-item-label end-indent="label-end()">
<fo:block>(<xsl:value-of select="position()"/>)</fo:block>
</fo:list-item-label>
<fo:list-item-body start-indent="body-start()">
<xsl:apply-templates/>
</fo:list-item-body>
</fo:list-item>
</xsl:template>
<xsl:template match="ListItemAttributeOne">
<fo:block>List Item Attribute One: <xsl:value-of select="."/></fo:block>
</xsl:template>
<xsl:template match="ListItemAttributeTwo">
<fo:block>List Item Attribute Two: <xsl:value-of select="."/></fo:block>
</xsl:template>
</xsl:stylesheet>
You may need to tweak it to your specific needs (page size, margins, fonts, ...) but it should give you a general idea.
I'm using fop to convert xml to pdf, so for that I have written an xslt code.
In the same xslt, I have used java code but somehow I get an error stating nosuchmethodexception : couldn't find method org.apache.xml.utils.NodeVector.input([ExpressionContext,]).
But my java code is a user defined code which is in a different package.
My xml has local_curr attribute.
My java class name is XMLData.
Package is com.pdf
Java Method is input which takes a String value and returns a String
xslt code :
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format"
xmlns:java="com.pdf.XMLData">
<xsl:output method="xml" indent="yes" />
<xsl:template match="/">
<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
<!-- Defining Page Layout -->
<fo:layout-master-set>
<fo:simple-page-master master-name="A3-portrait"
page-height="29.7cm" page-width="40.0cm" margin="2cm">
<fo:region-body margin-bottom="20mm" />
</fo:simple-page-master>
</fo:layout-master-set>
<fo:page-sequence master-reference="A3-portrait">
<fo:flow flow-name="xsl-region-body">
<fo:table table-layout="fixed" width="100%" border-width="1mm"
border-collapse="separate">
<fo:table-row>
<fo:table-cell background-color="#F79F81"
border-width="0.1mm" border-style="solid">
<fo:block wrap-option="wrap" font-size="15pt"
padding="5pt" text-align="right">
<xsl:value-of select="java:input(#local_curr)" />
</fo:block>
</fo:table-cell>
</fo:table-row>
</fo:table>
</fo:flow>
</fo:page-sequence>
</fo:root>
</xsl:template>
</xsl:stylesheet>
The problem is that #local_curr probably does not return the type your java method is expecting.
You need to parse it for example as a string
<xsl:value-of select="java:input(string(#local_curr))" />
Or as a number
<xsl:value-of select="java:input(number(#local_curr))" />
The NoSuchMethodException was thrown because no method was found with the given type as argument.
Thanks for the help.
It is resolved. Actually I have to add my jar file in the batch file of fop which resolved my problem.
Thanks...
I am using Apache FOP for PDF generation.I want to use unparsed-text() function to read non-xml document in XSL file.
After writing that function i got this error.
This is my XSL file.
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format"
xmlns:f="Functions">
<xsl:variable name="properties" select="unparsed-text('file.properties')" as="xs:string"/>
<xsl:function name="f:getProperty" as="xs:string?">
<xsl:param name="key" as="xs:string"/>
<xsl:variable name="lines" as="xs:string*" select="
for $x in
for $i in tokenize($properties, '\n')[matches(., '^[^!#]')] return
tokenize($i, '=')
return translate(normalize-space($x), '\', '')"/>
<xsl:sequence select="$lines[index-of($lines, $key)+1]"/>
</xsl:function>
<xsl:template match=" EmployeeData">
<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
<fo:layout-master-set>
<fo:simple-page-master master-name="simple"
page-height="20cm" page-width="10.5cm" margin-left="0.2cm"
margin-right="0.2cm">
<fo:region-body margin-top="0.5cm" />
</fo:simple-page-master>
</fo:layout-master-set>
<fo:page-sequence master-reference="simple">
<xsl:variable name="lang" select="language" />
<fo:flow flow-name="xsl-region-body">
From Properties File <xsl:value-of select="f:getProperty('language')"/>
</fo:flow>
</fo:page-sequence>
</fo:root>
</xsl:template>
</xsl:stylesheet>
How can i remove this error? Or give me any alternative for that if possible.
Thank you.
The error suggests you are using an XSLT 1.0 processor to run the XSLT. unparsed-text is only supported by XSLT 2.0 processors like Saxon 9.
I have a problem with printing PDF file from a Java project that is adding parameters in the XLS file. The project read the XML file, then he is generate a PDF file from the XSL style sheet. See below for the content of the files.
As you see in the XLS file I want to specified at “studentNumber”, but the problem is that is specified “studentNumber” need to set in the Java project. I have tried a lot of thing and search on internet but I cannot find the answer.
Any idea want I need to change to make this project proper.
XML file:
<?xml version="1.0" encoding="ISO-8859-1"?>
<?xml-stylesheet type="text/xsl" href="studentResultXLS.xsl"?>
<cursus>
<enroll>
<studentnumber>s484766</studentnumber>
<cursuscode>ISDTCEX.B627</cursuscode>
<enrolldate dateformat="eejjmmdd">20111121</enrolldate>
<acquire>ja</acquire>
<grade>4</grade>
<result></result>
</enroll>
<enroll>
<studentnumber>s484766</studentnumber>
<cursuscode>ISDTSIP.T470</cursuscode>
<enrolldate dateformat="eejjmmdd">20111116</enrolldate>
<acquire>ja</acquire><grade>2</grade>
<result></result>
</enroll>
<enroll>
<studentnumber>s484767</studentnumber>
<cursuscode>ISDTSIP.T470</cursuscode>
<enrolldate dateformat="eejjmmdd">20111116</enrolldate>
<acquire>ja</acquire><grade>2</grade>
<result></result>
</enroll>
</cursus>
XLS file:
<xsl:param name="studentnumber"/>.....
<fo:table-body>
<xsl:for-each select="/cursus/enroll[studentnumber='s484766']">
<fo:table-row>
<fo:table-cell>
<fo:block> <xsl:value-of select="studentnumber"/> </fo:block>
</fo:table-cell>
<fo:table-cell>
<fo:block> <xsl:value-of select="cursuscode"/> </fo:block>
</fo:table-cell>
</fo:table-row>
</xsl:for-each>
</fo:table-body>
Java code:
transformer.setParameter("studentnumber", "s484766");
For reading the parameter value, you need to prefix it with a $ sign:
<xsl:value-of select="$studentnumber"/>
I am trying to use fop Quick Start Guide to print a simple PDF file from a simple XML file and it works fine. but when I change <name>Frank</name> to <name>امیررضا</name> (change name to other encoding) I get #### in my printed PDF. I search through the Internet and couldn't find any feasible solution. I use many config files here are some of my them:
I use this command for creating pdf:
fop -c cfg.xml -xml name.xml -xsl name2fo.xsl -pdf name.pdf
When I use this command I get below warning:
WARNING: xHeight value could not be determined. The font may not work as
Sep 15, 2011 9:15:37 AM org.apache.fop.events.LoggingEventListener proce
WARNING: Glyph "╙" (0x633, afii57427) not available in font "Helvetica".
Sep 15, 2011 9:15:37 AM org.apache.fop.events.LoggingEventListener proce
WARNING: Glyph "╘" (0x634, afii57428) not available in font "Helvetica".
1- name.xml contains:
<name>امیررضا</name>
2-name2fo.xsl contains:
<?xml version="1.0" encoding="utf-8"?>
<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="A4-portrait"
page-height="29.7cm" page-width="21.0cm" margin="2cm">
<fo:region-body/>
</fo:simple-page-master>
</fo:layout-master-set>
<fo:page-sequence master-reference="A4-portrait">
<fo:flow flow-name="xsl-region-body">
<fo:block>
Hello, <xsl:value-of select="name"/>!
</fo:block>
</fo:flow>
</fo:page-sequence>
</fo:root>
</xsl:template>
</xsl:stylesheet>
3- have try many different config file (cfg.xml).
3.1:
<fop version="1.0">
<renderers>
<renderer mime="application/pdf">
<fonts>
<substitutions>
<substitution>
<from font-family="Helvetica" />
<to font-family="SansSerif"/>
</substitution>
</substitutions>
<referenced-fonts>
<match font-family=".*"/>
</referenced-fonts>
<!-- register all the fonts found in a directory and all of its sub directories (use with care) -->
<directory recursive="true">G:\....\fop\fop-1.0\Core14_AFMs</directory>
<!-- automatically detect operating system installed fonts -->
<auto-detect/>
<font embed-url="C:\WINDOWS\Fonts\times.ttf">
<font-triplet name="Times New Roman" style="normal" weight="normal"/>
</font>
</fonts>
</renderer>
</renderers>
</fop>
3.2:
<fop version="1.0">
<renderers>
<renderer mime="application/pdf">
<fonts>
<substitutions>
<substitution>
<from font-family="Helvetica" />
<to font-family="SansSerif"/>
</substitution>
</substitutions>
<referenced-fonts>
<match font-family=".*"/>
</referenced-fonts>
<!-- automatically detect operating system installed fonts -->
<auto-detect/>
</fonts>
</renderer>
</renderers>
</fop>
3.3: ......
The result output is:
Hello, #######!
Can anyone help me fix this?
Support for languages written with right-to-left scripts such as Arabic & Hebrew and full bidi support was added in Apache FOP 1.1. Based on the date of this question, an older Apache FOP version was used. For more information, see http://xmlgraphics.apache.org/fop/trunk/complexscripts.html.
I have never used Apache FOP but I found this article that allows you to create multiple language PDF.
Creating Multiple Language PDFs using Apache FOP
I would recommend that you use HelveticaWorld thatcontains arabic characters too or if you create the FOP input dynamically, then you can use Velocity or Freemarker variables to store the Font name.
I solve the problem by add font-family in XSL code:
name2fo.xsl after changes contains:
<?xml version="1.0" encoding="utf-8"?>
<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="A4-portrait"
page-height="29.7cm" page-width="21.0cm" margin="2cm">
<fo:region-body/>
</fo:simple-page-master>
</fo:layout-master-set>
<fo:page-sequence master-reference="A4-portrait">
<fo:flow flow-name="xsl-region-body">
<fo:block font-size="10pt" font-family="Tahoma">
Hello, <xsl:value-of select="name"/>!
</fo:block>
</fo:flow>
</fo:page-sequence>
</fo:root>
</xsl:template>
</xsl:stylesheet>
But I still have problem which is my Farsi character printed in reverse order. I mean if I want to print "Hello" it was printed "oellH" (you can imagine Hello is written in Farsi character) and also have a second problem that is the character was printed separated.