PDFs are one of the most common and most significant document
formats on the internet. Typically, developers must use expensive
tools from Adobe or cumbersome APIs to generate PDFs. In this
article, you will learn how to programmatically generate PDFs easily
with plain XHTML and CSS using two open source Java libraries:
Flying Saucer and iText.
The Problem with PDFs
PDFs are a great technology. When Adobe created the PDF format, they had a
vision for a portable document format (hence the name) that could
be viewed on any computer and printed to any printer. Unlike web
pages, PDFs will look exactly the same on every device, thanks to
the rigorous PDF specification. And the best thing about PDFs is
that the specification is open so you can generate them on the fly,
using readily available open source libraries.
There is one big problem with PDFs, however: the spec is
complicated and the APIs for generating PDFs tend to be cumbersome,
requiring a lot of low-level coding of paragraphs and headers. More
importantly, you have to use code to generate PDFs. But to
make good-looking PDFs, you need a graphic designer to create the
layout. Even if graphic designers are up to the task of
programming, they still must convert their layout from some other
format to code, which can be cumbersome, buggy, and time-consuming.
Fortunately, there is a better way.
The way to make good looking PDFs is to let the programmers do
what they are good at: writing code that manipulates data, and let
the graphic designers do what they are good at: making attractive
graphic designs. Flying Saucer and iText are tools that do this.
They let you render CSS stylesheets and XHTML, either static or
generated, directly to PDFs.
An Introduction to Flying Saucer and iText
Flying Saucer, which is the common name for the xhtmlrenderer project on
java.net, is an LGPLed Java library on java.net originally
created by me and continually developed by the java.net community.
Download it from the project page, or use the copy included with
this article's sample code (see Resources). Flying Saucer's primary purpose is to
render spec-compliant XHTML and CSS 2.1 to the screen as a Swing
component. Though it was originally intended for embedding markup
into desktop applications (things like the iTunes Music Store),
Flying Saucer has been extended work with iText as well. This makes
it very easy to render XHTML to PDFs, as well as to images and to the
screen. Flying Saucer requires Java 1.4 or higher.
iText is a PDF generation library created by Bruno
Lowagie and Paulo Soares, licensed under the LGPL and the Mozilla
Public License. You can download iText from its home page or use the copy
in the download bundle at the end of this article (see Resources). Using the iText API, you can produce
paragraphs, headers, or any other PDF feature. Since the PDF
imaging model is fairly similar to Java2D's model, Flying Saucer
and iText can easily work together to produce PDFs. In fact, the
PDF version of the Flying
Saucer user manual was itself produced using Flying Saucer and
iText.
Generating a Simple PDF
To get started, I'm going to show you how to render a very
simple HTML document as a PDF file. You can see in the
samples/firstdoc.xhtml file below that it's a plain XHTML
document (note the XHTML DTD in the header) and contains only a
single formatting rule: b { color: green; }. This
means the default HTML formatting for paragraphs and text will
apply, with the exception that all b elements will be
green.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>My First Document</title>
<style type="text/css"> b { color: green; } </style>
</head>
<body>
<p>
<b>Greetings Earthlings!</b>
We've come for your Java.
</p>
</body>
</html>
Now that we have a document, we need code to produce the PDF. The
FirstDoc.java file below is the simplest possible way to
render a PDF document.
package flyingsaucerpdf;
import java.io.*;
import com.lowagie.text.DocumentException;
import org.xhtmlrenderer.pdf.ITextRenderer;
public class FirstDoc {
public static void main(String[] args)
throws IOException, DocumentException {
String inputFile = "samples/firstdoc.xhtml";
String url = new File(inputFile).toURI().toURL().toString();
String outputFile = "firstdoc.pdf";
OutputStream os = new FileOutputStream(outputFile);
ITextRenderer renderer = new ITextRenderer();
renderer.setDocument(url);
renderer.layout();
renderer.createPDF(os);
os.close();
}
}
There are two main parts to the code. First it prepares the
input and output files. Since Flying Saucer deals with input URLs,
the code above converts a local file string into a
file:// URL using the File class. The
output document is just a FileOutputStream that
writes to the firstdoc.pdf file in the current working
directory.
The second part of the code creates a new
ITextRenderer object. This is the Flying Saucer class
that knows how to render PDFs using iText. You must first set the
document property of the renderer using the
setDocument(String) method. There are other methods
for setting the document using URLs and W3C DOM objects. Once the
document is installed you must call layout() to
perform the actual layout of the document and then
createPDF() to draw the document into a PDF file on
disk.
To compile and run this code you need the Flying Saucer .jar,
core-renderer.jar. For this article I am using a recent
development build (R7 HEAD). R7 final should be out in
a few weeks, perhaps by the time you read this. I chose to use a recent
R7 build instead of the year-old R6 because R7 has a rewritten CSS
parser, better table support, and of course, many, many bugfixes.
You will also need the iText .jar itext_paulo-155.jar (this
is actually an early access copy of iText from its SourceForge project
page). All of these .jars are included in the standard Flying
Saucer R6 download, and also in the examples.zip file in
this article's Resources section. Once you put
these .jars in your classpath everything will compile and run. The
finished PDF looks like Figure 1:
Producing a PDF from static documents is useful, but it would be
more interesting if you could generate the markup programmatically.
Then you could produce documents that contain more interesting
content than simple static text.
Below is the code for a simple program that generates the
lyrics to the song "99 Bottles of Beer on the Wall." This song has
a repeated structure, so we can easily produce the lyrics with a
simple loop. This document also uses some extra CSS styles like
color, text transformation, and modified padding.
In first part of the OneHundredBottles.java code, all of
the style and markup is appended to a StringBuffer.
Note that the style rule for h3 includes the
text-transform property. This will capitalize the
first letter of every word in the title. The body of the document
is produced by the loop that goes from 99 to 0. Notice that there
is an image, 100bottles.jpg, included at the top of
the document. iText will embed the image in the resulting PDF,
meaning the user will not need to load any other images once they
receive the PDF. This is an advantage of PDFs over HTML, where
images must be stored separately.
public class OneHundredBottles {
public static void main(String[] args) throws Exception {
StringBuffer buf = new StringBuffer();
buf.append("<html>");
// put in some style
buf.append("<head><style language='text/css'>");
buf.append("h3 { border: 1px solid #aaaaff; background: #ccccff; ");
buf.append("padding: 1em; text-transform: capitalize; font-family: sansserif; font-weight: normal;}");
buf.append("p { margin: 1em 1em 4em 3em; } p:first-letter { color: red; font-size: 150%; }");
buf.append("h2 { background: #5555ff; color: white; border: 10px solid black; padding: 3em; font-size: 200%; }");
buf.append("</style></head>");
// generate the body
buf.append("<body>");
buf.append("<p><img src='100bottles.jpg'/></p>");
for(int i=99; i>0; i--) {
buf.append("<h3>"+i+" bottles of beer on the wall, "
+ i + " bottles of beer!</h3>");
buf.append("<p>Take one down and pass it around, "
+ (i-1) + " bottles of beer on the wall</p>\n");
}
buf.append("<h2>No more bottles of beer on the wall, no more bottles of beer. ");
buf.append("Go to the store and buy some more, 99 bottles of beer on the wall.</h2>");
buf.append("</body>");
buf.append("</html>");
The second part of the code parses the
StringBufferinto a DOM document using the standard
Java XML APIs and then sets that as the document on the
ITextRenderer object. The renderer needs a base
URL to load resources like images and external CSS files. If
you pass a URL for the document to the renderer, then it will infer
the base URL. For example the document URL
http://myserver.com/pdf/mydoc.xhtml would result in a base
URL of http://myserver.com/pdf/ However, if you pass in a
pre-parsed Document object instead of a URL, then the
renderer will have no idea what the base URL is. You can manually
set the base URL using the second argument to the
setDocument() method. In this case I have used a value
of null, since I am not referencing any external
resources.
// parse the markup into an xml Document
DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
Document doc = builder.parse(new StringBufferInputStream(buf.toString()));
ITextRenderer renderer = new ITextRenderer();
renderer.setDocument(doc, null);
String outputFile = "100bottles.pdf";
OutputStream os = new FileOutputStream(outputFile);
renderer.layout();
renderer.createPDF(os);
os.close();
}
}
So far the documents we have rendered are basically just web
pages in PDF form. They don't have any features that take
advantage of pages. Paged media like printed documents or
slideshows have certain features specific to pages. In particular,
pages have specific sizes and margins. Text laid out for an 8 1/2
by 11 inch piece of paper will look very different than text for a
paperback book, or a CD cover. In short, pages matter, and Flying
Saucer gives you some control over pages using page-specific
features in CSS.
This next example will print the first chapter of Lewis
Carroll's Alice in Wonderland in a paperback format. The
markup is pretty straightforward, just a bunch of headers and
paragraphs. Below are the first few paragraphs of the document (see
the download for the entire chapter). There are two things to
notice in this document. First, all of the style is included in the
alice.css file linked in the header with a link
element. The media="print" attribute must be included,
or the style will not be loaded. The other important thing to
notice are the two divs at the top: header
and footer. The footer has two special elements in it,
pagenumber and pagecount, which are used
to generate the page numbers. These divs and the page
number elements will not be rendered at the top of the page.
Instead, we will use some special CSS to make these
divs repeat on every page and generate the proper page
numbers at runtime.
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Alice's Adventures in Wonderland -- Chapter I</title>
<link rel="stylesheet" type="text/css" href="alice.css" media="print"/>
</head>
<body>
<div id="header" style="">Alice's Adventures in Wonderland</div>
<div id="footer" style=""> Page <span id="pagenumber"/> of <span id="pagecount"/> </div>
<h1>CHAPTER I</h1>
<h2>Down the Rabbit-Hole</h2>
<p class="dropcap-holder">
<div class="dropcap">A</div>
lice was beginning to get very tired of sitting by her sister
on the bank, and of having nothing to do: once or twice she had
peeped into the book her sister was reading, but it had no pictures
or conversations in it, `and what is the use of a book,' thought
Alice `without pictures or conversation?'
</p>
<p>So she was considering in her own mind (as well as she could,
for the hot day made her feel very sleepy and stupid), whether the
pleasure of making a daisy-chain would be worth the trouble of
getting up and picking the daisies, when suddenly a White Rabbit
with pink eyes ran close by her. </p>
<p class="figure">
<img src="alice2.gif" width="200px" height="300px"/>
<br/>
<b>White Rabbit checking watch</b>
</p>
... the rest of the chapter
Most of the alice.css file contains normal CSS rules
that can apply to any kind XHTML document, printed or not. There
are a few, however, that are page-specific extensions:
The first thing you'll notice in the CSS above is the
@page rule. This is a rule that is attached to the
page itself rather than to any particular elements within the
document. Within this @page rule, you can set the size
of the page as well as page margins using the size and
margin properties. Note that I have set the size to
4.18in 6.88in, which is the size of a standard mass-market paperback book in the U.S. (according to CafePress). Also in the
@page rule are four special properties beginning with
-fs-flow-. These are Flying Saucer-specific properties
that tell the renderer to move content marked with the specified
names: header, footer, left,
and right to every page in the top, bottom, left, and
right positions.
In the rules for the header and footer divs, you
can see another Flying Saucer-specific property called
-fs-move-to-flow, which will take the div
out of the normal document and put it in the special place marked
by "footer" or "header". This property
works in conjunction with the -fs-flow-* properties in
the @page element to make repeated content work. These
custom properties are needed because CSS 2.1 does not define any
way to have repeated headers and footers. CSS 3 does
define a way to have repeated content, and Flying Saucer will
support the new standard mechanism in the future.
After the @page and header rules, you'll find two
more rules for the pagenumber and
pagecount elements. These are made-up elements (not
standard XHTML) that will have counters added to their content.
Since those two elements are empty, you will only see the counters
themselves. Since the pagenumber and
pagecount elements were defined in the footer, the
final page numbers will also appear in the footer. Again, these page
number elements will be replaced with their proper CSS 3
equivalents in the future.
The final rendered alice.xhtml is shown in Figure 3:
A quick note on debugging: CSS can be tricky sometimes, and it is
very easy to misspell a keyword or forget some punctuation. Flying
Saucer R7 has a brand new CSS parser with very robust error
reporting. When developing your application, I recommend turning on
the built-in logging. The in-depth details of Flying Saucer
configuration are available in the FAQ. I have found the most
useful setting is to set the logging level to INFO by
adding this to your Java command line:
This setting will print lots of debugging information, including
places where the CSS or markup may be broken.
Rendering Generic XML Instead of XHTML
Every example so far has used XHTML, meaning the XHTML dialect
of XML defined by the W3C. Many documents rendered into PDF are in
fact XHTML documents, but Flying Saucer can actually handle any
well-formed XML file. In fact, Flying Saucer does very little that
is XHTML-specific. XHTML documents are just XML documents with a
default stylesheet. If you define your own stylesheet, then you can
render any XML document you want. This could be particularly useful
when working with the output of databases or web services, since
that output is probably in XML already.
Below is a very simple custom XML document, weather.xml,
that describes the weather at multiple locations. It does not use
standard XHTML elements at all; every element is custom. Notice the
second line contains a reference to the stylesheet.
Here is the DirectXML.java code that renders the
document. Notice that the code does nothing special. As far as
Flying Saucer is concerned, the only difference between XHTML and
XML is the file extension.
public class DirectXML {
public static void main(String[] args) throws IOException, DocumentException {
String inputFile = "samples/weather.xml";
String outputFile = "weather.pdf";
OutputStream os = new FileOutputStream(outputFile);
ITextRenderer renderer = new ITextRenderer();
renderer.setDocument(new File(inputFile));
renderer.layout();
renderer.createPDF(os);
os.close();
}
}
Here's the weather.css CSS that will style the XML.
The CSS stylesheet contains all of the magic in this example.
Since this is all XML, there are no default rules to show how any
element is drawn. That's why the first rule is a *
rule to affect all elements: they should all be blocks with no
border, margins, or padding. Then I have defined a rule for each of
the four content elements. The elements take the standard CSS
properties that you could apply to HTML elements. Note that the
station element has a page-break-inside:
avoid property. This is a CSS 3 property that tells the
renderer that you don't want the station element split by a page
break. This is useful when you have content sections that must be printed
whole. For example you might be printing to label paper for
stickers on a map display. In that case, you definitely would
not want any boxes to be split across pages.
Note that I've set the size of the station block using inches.
When coding for the Web you usually want to avoid absolute units
like inches, pixels, or centimeters. Instead, you should use
relative units like points or ems, since these work well when a
user resizes the document or changes their font size. But then
again, PDFs aren't for the Web. They are paged media for
printing. That means absolute units are perfectly fine, and in fact
encouraged, since their use ensures the user will get a document
that looks exactly like you wanted.
All of the examples in this article have been small command-line
programs that write PDF files. However, you can easily use this
technology to produce PDFs in a web application using a servlet.
The only difference is that you will be writing to a
ServletOutputStream instead of a
FileOutputStream. Below is a portion of the code for a
PDF generation servlet that produces a tabular report of sales for
a particular user:
public class PDFServlet extends HttpServlet {
protected void processRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("application/pdf");
StringBuffer buf = new StringBuffer();
buf.append("<html>");
String css = getServletContext().getRealPath("/PDFservlet.css");
// put in some style
buf.append("<head><link rel='stylesheet' type='text/css' "+
"href='"+css+"' media='print'/></head>");
... //generate the rest of the HTML
// parse our markup into an xml Document
try {
DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
Document doc = builder.parse(new StringBufferInputStream(buf.toString()));
ITextRenderer renderer = new ITextRenderer();
renderer.setDocument(doc, null);
renderer.layout();
OutputStream os = response.getOutputStream();
renderer.createPDF(os);
os.close();
} catch (Exception ex) {
ex.printStackTrace();
}
}
The code above looks pretty much like the previous examples.
There are two special things to notice, though. First, you must set
the content type to application/pdf. This will make
the user's web browser pass the PDF on to their PDF reader or
plugin instead of showing it as garbled text. Second, the CSS is
stored in a separate file in the main webapp directory (where the
JSPs and HTML would go). In order for Flying Saucer to find it, you
must use the getServletContext().getRealPath() method
to convert PDFservlet.css into an absolute URL and put
it in the link tag at the top of the generated markup. Once you
have your HTML properly generated, you can just parse it into a
Document and render the PDF to the output stream
returned by response.getOutputStream().
PDFs are a great format for maps, receipts, reports, and
printable labels. Flying Saucer and iText let you produce PDF files
programmatically without having to use expensive tools or
cumbersome APIs. By using plain XHTML and CSS, your graphic
designer can use their existing web tools like Dreamweaver to
produce great looking CSS templates that you or your developers
plug in to your applications. By splitting the work, you can save
both time and money.
If you use Flying Saucer to produce PDFs for your company or
project, please post a link in the comments of this article or email
me. The Flying Saucer team would love to have more examples of cool
things people are doing with Flying Saucer and iText.
Did you know Flying Saucer generated PDFs? What do you think?
Showing messages 1 through 46 of 46.
cmyk color definition
2008-07-07 05:03:11 krivitsky
[Reply | View]
Hi
We're thinking about using xhtmlrenderer for rendering printing quality PDFs. So far it looks very promising.
The only thing we found missing so far is CSS cmyk color declaration:
http://www.w3.org/TR/css3-gcpm/#cmyk-colors
The lib prints out the following:
plumbing.css-parse WARNING:: Value for color must be an identifier or a color at line 18. Skipping declaration.
So seems it is not implemented. So the questions are:
1. is it planned for nearest versions of the API?
2. if not, how complex it might be for us to add this functionality (contributing to the project)?
Thanks a lot!
Waiting for the reply soon.
Image does not show on the PDF page
2008-05-22 19:18:32 jexplorer
[Reply | View]
Hi, I am new to java. I tried to used the xhtmlrenderer to generate the pdf, the pdf was successfully generated, anchor links work within the page, but image didnot show up, internal links and external links shows as links but are not linkable? Did I missing anything? Any suggestions is greatly appreciate it.
Image does not show on the PDF page
2008-05-22 21:51:01 jexplorer
[Reply | View]
I outputed the xhtml and saved it as html file, displayed in the browser, image and links are display fine. But then image and links did not show in the pdf page after going through iText.
But it don't work in netbeans modules and suite modules
"getCharBBox" method is not there in the given "itext-paulo-155.jar"
2008-03-18 05:59:08 rajjj
[Reply | View]
getting method not found exception.Please provide the zar file with the specified method.
Problem with DirectXML example
2008-02-29 14:41:32 robmoore
[Reply | View]
I've found an issue in the case where the the xml file is not in a subdirectory (such as samples) but rather is at the same directory (aka user.dir). So when I create the File object with simply "weather.xml" (rather than "samples/weather.xml") an exception is thrown: org.xhtmlrenderer.util.XRRuntimeException: IOException on parsing style seet from a Reader; don't know the URI.
This error is triggered by the fact that in ITextRenderer.setDocument() the call to file.getParentFile() returns null. The code checks for that and substitutes an empty string for the value passed into setDocument(). The empty string does not appear to be resolved correctly by the underlying code (NaiveUserAgent seems to have trouble resolving empty string properly when it comes to processing the css file). One possible solution would be for ITextRenderer to call file.getAbsoluteFile().getParentFile().toURI().toURL().toExternalForm() instead (since it will return a non-null value that is equivalent to what would be returned if the parent had been set in the file object).
For now, I'll just used new File(".", inputFile).
Thanks for the article!
Rob
Problem with DirectXML example
2008-03-04 13:20:04 robmoore
[Reply | View]
After getting over the first hurdle, I've run into another issue I'm hoping somebody can help me with. The PDF that's generated from the example looks different than the PDF example linked to within the article. The difference is the background on my PDF is green outside of the station element -- that is, it extends beyond the station border so that the whole page is green. So imagine a green page with the station boxes on it (also green) rather than islands of green boxes surrounded with a sea of white.
At first I thought this might be an issue resulting from my using a later version of Flying Saucer but I went back to the version used in the example available from the article and the results are the same.
Problem with DirectXML example
2008-03-11 10:12:57 joshy
[Reply | View]
It is possible that the markup in my example changed from when I made the sceenshots to when I published the article and zip file. Could you post your question to the Flying Saucer mailing list and we will help you there.
Thanks.
Problem with DirectXML example
2008-03-24 15:11:26 robmoore
[Reply | View]
Thanks for the reply, Josh.
I was able to fix the issue by applying background-color: white to the * block. Perhaps that was originally in your CSS as well?
Also, regarding my first issue with the File object, I posted to the Flying Saucer mailing list and an issue has been opened on it: https://xhtmlrenderer.dev.java.net/issues/show_bug.cgi?id=228
Extra blank page in PDF
2008-02-16 01:14:10 sowkot
[Reply | View]
Sometimes an extra blank page is found in the generated pdf and its the last page. We used header and footer in the pdf. Can anyone suggest why this problem occurs ? Or how to solve it?
Extra blank page in PDF
2008-02-18 08:38:31 joshy
[Reply | View]
I'm not sure. Could you join the Flying Saucer mailing list and post your question there?
Thanks,
Josh
use of jTidy for HTML =>XHTML => PDF ?
2008-01-02 08:06:54 benoit_noss
[Reply | View]
I read with interest the two following articles:
Generating PDFs for Fun and Profit with Flying Saucer and iText
Java Sketchbook: The HTML Renderer Shootout, Part 1&2
FlyingSaucer/iText only generate PDF from X(HT)ML.
Did anyone tried
HTML ===jTidy ===> XHTML ===FlyingSaucer/iText ===> PDF ?
Any help greatly appreciated
Ben
multi-user PDF generation
2007-11-19 14:39:08 finhead
[Reply | View]
We're using the Flying Saucer project, to render our XHTML pages into PDFs.
We've had a lot of success, except when we start getting a large number of users on the server. The PDFs take longer and longer to run and eventually they start timing out and crashing the web app.
Has anyone experienced this problem and have any suggestions?
Thanks,
Jason
Last page of "Alice in ...." is Blue...
2007-10-15 15:50:28 netmille
[Reply | View]
Hello,
I downloaded the sample code and noticed
that once .pdf is generated, the last page of the "Alice in Wonderland" article is blue.
Can someone explain why?
Thanks!
Last page of "Alice in ...." is Blue...
2007-10-15 15:50:01 netmille
[Reply | View]
Ahh,
Figured it out. In the alice.css file:
html {
background-color: white;
}
I updated background-color to 'white'.
Great article!
How do I keep my content within the page?
2007-10-08 17:36:24 danubruin
[Reply | View]
I've been trying to figure out how to keep my content within the pdf. I'm generating some dynamic content within a JSP and I'm using the javax.servlet.Filter class to capture the response and convert it to a PDF. However the problem I'm facing is that I can't consistently keep the content within the PDF page. If the html that gets generated is too wide, the full content gets cut off on the right. Is there a way with stylesheets to keep the content within the page without it getting cut off?
Anyone got any suggestions?
Problem with multilingual content
2007-09-12 11:37:50 nskclr
[Reply | View]
I use the below code to convert German xhtml to pdf. But the pdf generated has dots. What should I do to get the desired pdf output?
ITextRenderer renderer = new ITextRenderer();
renderer.setDocument(url);
renderer.layout();
renderer.createPDF(os);
Problem with multilingual content
2007-09-13 17:01:53 nskclr
[Reply | View]
I even tried with other language with the code below
More advanced page numbering
2007-09-06 18:08:24 tietyt
[Reply | View]
Hello,
Is it possible to do more advanced page numbering? Specifically, I would like the footer to not show up til page three, and label that page #2 (because i'm generating documents with coverletters attached and the cover letter shouldn't count as a page).
If this isn't possible ATM, could someone tell me where to look in the source to add this functionality?
Thanks
More advanced page numbering
2007-09-06 18:25:56 joshy
[Reply | View]
FlyingSaucer only supports what CSS 2.1 supports, with a few extensions. Unfortunately CSS 2.1 has weak printing support. However, in recent builds Peter has been introducing support for some of the CSS 3 properties. Thus it may be possible to do what you want now, or at least be easy to add. Please join the mailing list and ask about it.
More advanced page numbering
2007-09-07 11:44:04 tietyt
[Reply | View]
I tried emailing dev@xhtmlrenderer.dev.java.net after I signed up, but my email didn't go into the mailing list archives. Maybe it takes a while. Here was my email message:
I have a request for complex pagination in flying saucer.
Specifically, I'm generating a document where I want page 3 to be
numbered as page 2, and I don't want the 2 pages before that to be
numbered.
Here's the scenario (if you care): I'm sending a document with a cover
letter attached to it. I don't want the cover letter to count as a
page and just to make things look a little bit nicer, i don't want the
first "real" page to be numbered.
I'm reading this spec
http://www.w3.org/TR/css3-page/#page-based-counters and I actually
don't see any ability to do this in css3 (I'm VERY weak in css so
maybe I should be reading a different document).
Regardless, I'm willing to implement this myself if I have to. Can
anyone give me any hints as to whether this is already possible or
where to look in the source to start?
More advanced page numbering
2007-09-07 16:33:27 tietyt
[Reply | View]
ok I'd like to let you guys know I figured out how to solve this problem by modifying the latest version of the code. Here is a detailed explanation of how I did this:
https://xhtmlrenderer.dev.java.net/issues/show_bug.cgi?id=197
BTW, I'm pretty sure that there is no ability to do this in the CSS3 spec. On the downside that means I had to implement code that is not part of a standard. On the upside, flyingsaucer has more advanced pagination than the CSS spec.
HUGE pitfall!!!
2007-09-06 18:06:22 tietyt
[Reply | View]
It took me 2 hours for me to figure this out so I thought I'd post it. If you want to try out page numbering, make sure you remove this from the top of your xhtml file (which happens to appear at the top of the first example):
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
If you leave that in there, you'll keep getting exceptions that say stuff like:
ERROR: 'NOT_FOUND_ERR: An attempt is made to reference a node in a context where it does not exist.'
This may be obvious to someone that knows xhtml, I just know html.
digital signatures (eID ?)
2007-08-21 04:44:57 peterv
[Reply | View]
Great :-)
Is it possible to sign the generated PDF's (with a certificate or eID ?).
Thanks, Peter Vandenabeele
problem with direct xml css application
2007-07-21 01:27:43 johnhaze1
[Reply | View]
please help!!!!!!!!!!!
why does the application of the css not work using this code?:
public static void main(String[] args) throws IOException,
DocumentException {
String inputFile = "weather.xml";
String outputFile = "weather.pdf";
try {
OutputStream os = new FileOutputStream(outputFile);
ITextRenderer renderer = new ITextRenderer();
DocumentBuilder builder = DocumentBuilderFactory.newInstance()
.newDocumentBuilder();
Document doc = builder.parse(new File(inputFile));
renderer
.setDocument(
doc,
"file:/C:/Dokumente%20und%20Einstellungen/johannes/Desktop/project_sem/PdfCreator/");
renderer.layout();
renderer.createPDF(os);
os.close();
problem with direct xml css application
2007-07-21 06:27:38 joshy
[Reply | View]
Could you tell me what it's doing? Is it throwing an exception? Is it rendering badly?
problem with direct xml css application
2007-07-21 01:36:06 johnhaze1
[Reply | View]
the result console output is
plumbing.render INFO:: Using CSS implementation from: org.xhtmlrenderer.context.StyleReference
plumbing.load INFO:: TIME: parse stylesheets 172ms
plumbing.match INFO:: media = print
plumbing.match INFO:: Matcher created with 118 selectors
problem with direct xml css application
2007-07-21 21:59:42 joshy
[Reply | View]
All of that output looks fine. What is it doing wrong?
problem with direct xml css application
2007-07-26 01:19:29 johnhaze1
[Reply | View]
Can you tell me a point in flyingsaucer sutiable to debug in and recognize whther the framework is applying the css stated in the source data xml file! Thanks!
problem with direct xml css application
2007-07-22 13:32:07 johnhaze1
[Reply | View]
OS: windows xp prof sp2
VM: 1.5.0 version 11
classpath: <classpath>
<classpathentry kind="src" path="src"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
<classpathentry kind="lib" path="lib/core-renderer.jar"/>
<classpathentry kind="lib" path="lib/itext-paulo-155.jar"/>
<classpathentry kind="output" path="bin"/>
</classpath>
problem with direct xml css application
2007-07-22 13:20:24 johnhaze1
[Reply | View]
all of the text between the xml nodes in weather xml are printed out in one line, each node value separated by one space. but it does not get to applying the css format information at all. Meanign that the rae text is printed but no blocks and colors, etc... I really struggle to get the point where the mistake lies. There is no exeption thrown. The xml and css file are all in the projet root folder, whose path I give the ITextRenderer.setDocument method as the baseUrl. As well the NaiveUserAgent, which i debugged is finding the css file so seems to have no problems (no exception) with using this baseUrl. If i do not use this base url and using the other setDocument method whcih only takes the read xml Fiel as an argument the ITextRenderer can't get the css --> Exceptio MalFormedUrl. Thanks for any hint!
problem with direct xml css application
2007-08-01 08:16:35 joshy
[Reply | View]
I posted the question to our mailing list and got an answer here. It looks like the media tag should be set to 'all'. I recommend everyone interested in Flying Saucer check out the lists as that's where all of our engineers hang out.
NO PROBLEM with direct xml css application
2007-08-02 02:28:07 johnhaze1
[Reply | View]
Thanks Josh! Including a media attribute in the xml-stylesheet solved the problem. Thanks a lot!!! the xml now loks like this ceteris paribus(css, java code):
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet href="weather.css" type="text/css" media="all" ?>
<weather>
<station>
<location>Springfield, NT</location>
<description>Sunny</description>
<tempf>85</tempf>
</station>
<station>
<location>Arlen, TX</location>
<description>Super Sunny</description>
<tempf>99</tempf>
</station>
<station>
<location>South Park, CO</location>
<description>Snowing</description>
<tempf>18</tempf>
</station>
</weather>
Printing with Flying Saucer
2007-07-17 06:29:10 wlenhard
[Reply | View]
Hello,
really a great article. This reliefs much of the report generating pain with java. I have read, that it is in principally possible to send the rendered documents to the printer, but I did not find a working example for this. Is there some example code for this?
Bye,
Wolfgang
Printing with Flying Saucer
2007-07-21 21:57:03 joshy
[Reply | View]
I recall there were some bugs in printing support (to be fixed in R8) but it's certainly possible. Anything that you can draw to the screen you can draw to the printer. Could you post your question on the Flying Saucer mailing list? Thanks.
problem rendering direct xml example
2007-07-10 06:59:36 johnhaze1
[Reply | View]
if I open the xml it gets rendered correctly automatically
by IE.<br/>
As I try to run this example it fails to apply the css information to the output. instead it just shows the text in the produced pdf. Seems to be that it does not choose the custom css to render the xml. <br/>Also I debugged the NameSpaceHandler and the uri to the css etc is ok, as my last resort was to exactly reproduce the examples. <br/>In Contrast to that, the example with the xhtml and the inline css style information worked perfectly. Any help would be higly appreciated!! <br/>Thanks in advance: here is the logging info:<br/> plumbing.render INFO:: Using CSS implementation from: org.xhtmlrenderer.context.StyleReference
<br/>plumbing.general INFO:: System property org.xml.sax.driver not specified
<br/>plumbing.load WARNING:: falling back on the default parser
<br/>plumbing.load INFO:: SAX XMLReader in use (parser): org.apache.crimson.parser.XMLReaderImpl
<br/>plumbing.general INFO:: System property org.xml.sax.driver not specified
<br/>plumbing.load WARNING:: falling back on the default parser
<br/>plumbing.load INFO:: SAX XMLReader in use (parser): org.apache.crimson.parser.XMLReaderImpl
<br/>plumbing.general INFO:: System property org.xml.sax.driver not specified
<br/>plumbing.load WARNING:: falling back on the default parser
<br/>plumbing.load INFO:: SAX XMLReader in use (parser): org.apache.crimson.parser.XMLReaderImpl
<br/>plumbing.general INFO:: System property org.xml.sax.driver not specified
<br/>plumbing.load WARNING:: falling back on the default parser
<br/>plumbing.load INFO:: SAX XMLReader in use (parser): org.apache.crimson.parser.XMLReaderImpl
<br/>plumbing.general INFO:: System property org.xml.sax.driver not specified
<br/>plumbing.load WARNING:: falling back on the default parser
<br/>plumbing.load INFO:: SAX XMLReader in use (parser): org.apache.crimson.parser.XMLReaderImpl
<br/>plumbing.general INFO:: System property org.xml.sax.driver not specified
<br/>plumbing.load WARNING:: falling back on the default parser
<br/>plumbing.load INFO:: SAX XMLReader in use (parser): org.apache.crimson.parser.XMLReaderImpl
<br/>plumbing.load INFO:: Loaded document in ~32ms
<br/>plumbing.load INFO:: TIME: parse stylesheets 109ms
<br/>plumbing.match INFO:: media = print
<br/>plumbing.match INFO:: Matcher created with 118 selectors
problem rendering direct xml example
2007-07-21 22:02:24 joshy
[Reply | View]
the stylesheet isn't being parsed for some reason. could you give my your system info? OS, JVM version, and your classpath? Thanks.
3D pdf is not Supporting..............
2007-06-29 04:54:33 manish_deo
[Reply | View]
3D PDF : I need help how to call 3D pdf using iText or java code. I'm not able to call. iText andFlying Saucer is good for normal PDF.
Please help me how to call 3D pdf using iText or is there any API is available to call 3D pdf.
Thanks.
3D pdf is not Supporting..............
2007-07-21 22:00:47 joshy
[Reply | View]
There is no 3D support in iText or Flying Saucer. You would have to have your own library to render the 3D into a static image.
It is really cool. I am using iText for generating PDF files in one of my projects, but with Flying Saucer it will be more easy and the result will be better.
I was using iReports + JasperRepors + XML DataSources to generate my PDF reports easily... but getting them straight from XHTML sounds very very interesting... I'll have to integrate that as another option in my framework, auch ;).
S!
Far Better than FOP
2007-06-27 04:55:52 eduardo_sasso
[Reply | View]
I have been using Apache FOP to generate my PDF's, but the lack of a free and good visual to design the XSL just kills me....
I will definetely check it out this new solution... it seems great!!!
This amazing package from the guy who said "Laying out your GUI is a visual task. Use a visual tool! End of story." I would argue that laying out documents is also a visual task, and yet here it all is controlled by text ...
;)
(Flying Saucer REALLY is cool)
Ha hah. :) That's true, the CSS is text. The important thing here is that the CSS is not code. It is a declarative syntax, not programmatic; and it is usually written by graphic designers, not programmers. And those graphic designers will use the help of a sophisticated visual tool like Dreamweaver rather than just a text editor. (Though I realize that Dreamweaver is not strictly WYSIWYG, it's definitely a visual tool).