123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680 |
- <?xml version="1.0" standalone="no"?>
- <!--
- Copyright 1999-2006 The Apache Software Foundation
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- -->
- <!-- $Id$ -->
- <!DOCTYPE document PUBLIC "-//APACHE//DTD Documentation V2.0//EN" "http://forrest.apache.org/dtd/document-v20.dtd">
- <!-- Embedding FOP -->
- <document>
- <header>
- <title>Apache FOP: Embedding</title>
- <subtitle>How to Embed FOP in a Java application</subtitle>
- <version>$Revision$</version>
- </header>
-
- <body>
- <section id="overview">
- <title>Overview</title>
- <p>
- Review <a href="running.html">Running FOP</a> for important information that applies
- to embedded applications as well as command-line use, such as options and performance.
- </p>
- <p>
- To embed Apache FOP in your application, instantiate a new org.apache.fop.apps.FopFactory
- instance and create a new org.apache.fop.apps.Fop instance through one of the factory
- methods of FopFactory. There, you can specify which output format (i.e. Renderer) to use
- and you can optionally set the OutputStream to use to output the results of the
- rendering. You can customize FOP's behaviour by supplying
- your own FOUserAgent instance. The FOUserAgent can, for example, be used to
- set your own Renderer instance (details below). Finally, you retrieve a SAX
- DefaultHandler instance from the Fop instance to which you can send your
- FO file.
- </p>
- <note>
- We recently changed FOP's outer API to what we consider the final API. This might require
- some changes in your application. The main reasons for these changes were performance
- improvements due to better reuse of reusable objects and reduced use of static variables
- for added flexibility in complex environments.
- </note>
- </section>
- <section id="basics">
- <title>Basic Usage Pattern</title>
- <p>
- Apache FOP relies heavily on JAXP. It uses SAX events exclusively to receive the XSL-FO
- input document. It is therefore a good idea that you know a few things about JAXP (which
- is a good skill anyway). Let's look at the basic usage pattern for FOP...
- </p>
- <p>Here is the basic pattern to render an XSL-FO file to PDF:
- </p>
- <source><![CDATA[
- import org.apache.fop.apps.FopFactory;
- import org.apache.fop.apps.Fop;
- import org.apache.fop.apps.MimeConstants;
-
- /*..*/
-
- // Step 1: Construct a FopFactory
- // (reuse if you plan to render multiple documents!)
- FopFactory fopFactory = FopFactory.newInstance();
-
- // Step 2: Setup output stream.
- // Note: Using BufferedOutputStream for performance reasons (helpful with FileOutputStreams).
- OutputStream out = new BufferedOutputStream(new FileOutputStream(new File("C:/Temp/myfile.pdf")));
-
- try {
- // Step 3: Construct fop with desired output format
- Fop fop = fopFactory.newFop(MimeConstants.MIME_PDF, out);
-
- // Step 4: Setup JAXP using identity transformer
- TransformerFactory factory = TransformerFactory.newInstance();
- Transformer transformer = factory.newTransformer(); // identity transformer
-
- // Step 5: Setup input and output for XSLT transformation
- // Setup input stream
- Source src = new StreamSource(new File("C:/Temp/myfile.fo"));
-
- // Resulting SAX events (the generated FO) must be piped through to FOP
- Result res = new SAXResult(fop.getDefaultHandler());
-
- // Step 6: Start XSLT transformation and FOP processing
- transformer.transform(src, res);
-
- } finally {
- //Clean-up
- out.close();
- }]]></source>
- <p>
- Let's discuss these 5 steps in detail:
- </p>
- <ul>
- <li>
- <strong>Step 1:</strong> You create a new FopFactory instance. The FopFactory holds
- references to configuration information and cached data. It's important to reuse this
- instance if you plan to render multiple documents during a JVM's lifetime.
- </li>
- <li>
- <strong>Step 2:</strong> You set up an OutputStream that the generated document
- will be written to. It's a good idea to buffer the OutputStream as demonstrated
- to improve performance.
- </li>
- <li>
- <strong>Step 3:</strong> You create a new Fop instance through one of the factory
- methods on the FopFactory. You tell the FopFactory what your desired output format
- is. This is done by using the MIME type of the desired output format (ex. "application/pdf").
- You can use one of the MimeConstants.* constants. The second parameter is the
- OutputStream you've setup up in step 2.
- </li>
- <li>
- <strong>Step 4</strong> We recommend that you use JAXP Transformers even
- if you don't do XSLT transformations to generate the XSL-FO file. This way
- you can always use the same basic pattern. The example here sets up an
- "identity transformer" which just passes the input (Source) unchanged to the
- output (Result). You don't have to work with a SAXParser if you don't do any
- XSLT transformations.
- </li>
- <li>
- <strong>Step 5:</strong> Here you set up the input and output for the XSLT
- transformation. The Source object is set up to load the "myfile.fo" file.
- The Result is set up so the output of the XSLT transformation is sent to FOP.
- The FO file is sent to FOP in the form of SAX events which is the most efficient
- way. Please always avoid saving intermediate results to a file or a memory buffer
- because that affects performance negatively.
- </li>
- <li>
- <strong>Step 6:</strong> Finally, we start the XSLT transformation by starting
- the JAXP Transformer. As soon as the JAXP Transformer starts to send its output
- to FOP, FOP itself starts its processing in the background. When the
- <code>transform()</code> method returns FOP will also have finished converting
- the FO file to a PDF file and you can close the OutputStream.
- <note label="Tip!">
- It's a good idea to enclose the whole conversion in a try..finally statement. If
- you close the OutputStream in the finally section, this will make sure that the
- OutputStream is properly closed even if an exception occurs during the conversion.
- </note>
- </li>
- </ul>
- <p>
- If you're not totally familiar with JAXP Transformers, please have a look at the
- <a href="#examples">Embedding examples</a> below. The section contains examples
- for all sorts of use cases. If you look at all of them in turn you should be able
- to see the patterns in use and the flexibility this approach offers without adding
- too much complexity.
- </p>
- <p>
- This may look complicated at first, but it's really just the combination of an
- XSL transformation and a FOP run. It's also easy to comment out the FOP part
- for debugging purposes, for example when you're tracking down a bug in your
- stylesheet. You can easily write the XSL-FO output from the XSL transformation
- to a file to check if that part generates the expected output. An example for that
- can be found in the <a href="#examples">Embedding examples</a> (See "ExampleXML2FO").
- </p>
- <section id="basic-logging">
- <title>Logging</title>
- <p>
- Logging is now a little different than it was in FOP 0.20.5. We've switched from
- Avalon Logging to <a href="ext:jakarta/commons/logging">Jakarta Commons Logging</a>.
- While with Avalon Logging the loggers were directly given to FOP, FOP now retrieves
- its logger(s) through a statically available LogFactory. This is similar to the
- general pattern that you use when you work with Apache Log4J directly, for example.
- We call this "static logging" (Commons Logging, Log4J) as opposed to "instance logging"
- (Avalon Logging). This has a consequence: You can't give FOP a logger for each
- processing run anymore. The log output of multiple, simultaneously running FOP instances
- is sent to the same logger.
- </p>
- <note>
- We know this may be an issue in multi-threaded server environments if you'd like to
- know what's going on in every single FOP processing run. We're planning to add an
- additional feedback facility to FOP which can be used to obtain all sorts of specific
- feedback (validation messages, layout problems etc.). "Static logging" is mainly
- interesting for a developer working on FOP and for advanced users who are debugging
- FOP. We don't consider the logging output to be useful to normal FOP users. Please
- have some patience until we can add this feature or jump in and help us build it. We've
- set up a <a href="http://wiki.apache.org/xmlgraphics-fop/ProcessingFeedback">Wiki page</a>
- which documents what we're going to build.
- </note>
- <p>
- By default, <a href="ext:jakarta/commons/logging">Jakarta Commons Logging</a> uses
- JDK logging (available in JDKs 1.4 or higher) as its backend. You can configure Commons
- Logging to use an alternative backend, for example Log4J. Please consult the
- <a href="ext:jakarta/commons/logging">documentation for Jakarta Commons Logging</a> on
- how to configure alternative backends.
- </p>
- </section>
-
- <section id="render">
- <title>Processing XSL-FO</title>
- <p>
- Once the Fop instance is set up, call <code>getDefaultHandler()</code> to obtain a SAX
- DefaultHandler instance to which you can send the SAX events making up the XSL-FO
- document you'd like to render. FOP processing starts as soon as the DefaultHandler's
- <code>startDocument()</code> methods is called. Processing stops again when the
- DefaultHandler's <code>endDocument()</code> method is called. Please refer to the basic
- usage pattern shown above to render a simple XSL-FO document.
- </p>
- </section>
-
- <section id="render-with-xslt">
- <title>Processing XSL-FO generated from XML+XSLT</title>
- <p>
- If you want to process XSL-FO generated from XML using XSLT we recommend
- again using standard JAXP to do the XSLT part and piping the generated SAX
- events directly through to FOP. The only thing you'd change to do that
- on the basic usage pattern above is to set up the Transformer differently:
- </p>
- <source><![CDATA[
- //before (without XSLT):
- //Transformer transformer = factory.newTransformer(); // identity transformer
-
- //after (with XSLT):
- Source xslt = new StreamSource(new File("mystylesheet.xsl"));
- Transformer transformer = factory.newTransformer(xslt);]]></source>
- </section>
- </section>
- <section id="input">
- <title>Input Sources</title>
- <p>
- The input XSL-FO document is always handled internally as SAX (see the
- <a href="../dev/design/parsing.html">Parsing Design Document</a> for the rationale).
- </p>
- <p>
- However, you may not always have your input document available as a SAX stream.
- But with JAXP it's easy to convert different input sources to a SAX stream so you
- can pipe it into FOP. That sounds more difficult than it is. You simply have
- to set up the right Source instance as input for the JAXP transformation.
- A few examples:
- </p>
- <ul>
- <li>
- <strong>URL:</strong> <code>Source src = new StreamSource("http://localhost:8080/testfile.xml");</code>
- </li>
- <li>
- <strong>File:</strong> <code>Source src = new StreamSource(new File("C:/Temp/myinputfile.xml"));</code>
- </li>
- <li>
- <strong>String:</strong> <code>Source src = new StreamSource(new StringReader(myString)); //myString is a String</code>
- </li>
- <li>
- <strong>InputStream:</strong> <code>Source src = new StreamSource(new MyInputStream(something));</code>
- </li>
- <li>
- <strong>Byte Array:</strong> <code>Source src = new StreamSource(new ByteArrayInputStream(myBuffer)); //myBuffer is a byte[] here</code>
- </li>
- <li>
- <strong>DOM:</strong> <code>Source src = new DOMSource(myDocument); //myDocument is a Document or a Node</code>
- </li>
- <li>
- <strong>Java Objects:</strong> Please have a look at the <a href="#examples">Embedding examples</a> which contains an example for this.
- </li>
- </ul>
- <p>
- There are a variety of upstream data manipulations possible.
- For example, you may have a DOM and an XSL stylesheet; or you may want to
- set variables in the stylesheet. Interface documentation and some cookbook
- solutions to these situations are provided in
- <a href="http://xml.apache.org/xalan-j/usagepatterns.html">Xalan Basic Usage Patterns</a>.
- </p>
- </section>
- <section id="config-internal">
- <title>Configuring Apache FOP Programmatically</title>
- <p>
- Apache FOP provides two levels on which you can customize FOP's
- behaviour: the FopFactory and the user agent.
- </p>
- <section id="fop-factory">
- <title>Customizing the FopFactory</title>
- <p>
- The FopFactory holds configuration data and references to objects which are reusable over
- multiple rendering runs. It's important to instantiate it only once (except in special
- environments) and reuse it every time to create new FOUserAgent and Fop instances.
- </p>
- <p>
- You can set all sorts of things on the FopFactory:
- </p>
- <ul>
- <li>
- <p>
- The <strong>font base URL</strong> to use when resolving relative URLs for fonts. Example:
- </p>
- <source>fopFactory.setFontBaseURL("file:///C:/Temp/fonts");</source>
- </li>
- <li>
- <p>
- Disable <strong>strict validation</strong>. When disabled FOP is less strict about the rules
- established by the XSL-FO specification. Example:
- </p>
- <source>fopFactory.setStrictValidation(false);</source>
- </li>
- <li>
- <p>
- Enable an <strong>alternative set of rules for text indents</strong> that tries to mimic the behaviour of many commercial
- FO implementations that chose to break the specification in this aspect. The default of this option is
- 'false' which causes Apache FOP to behave exactly as describes in the specification. To enable the
- alternative behaviour, call:
- </p>
- <source>fopFactory.setBreakIndentInheritanceOnReferenceAreaBoundary(true);</source>
- </li>
- <li>
- <p>
- Set the <strong>source resolution</strong> for the document. This is used internally to determine the pixel
- size for SVG images and bitmap images without resolution information. Default: 72 dpi. Example:
- </p>
- <source>fopFactory.setSourceResolution(96); //=96dpi (dots/pixels per Inch)</source>
- </li>
- <li>
- <p>
- Manually add a <strong>ElementMapping instance</strong>. If you want to supply a special FOP extension
- you can give the instance to the FOUserAgent. Normally, the FOP extensions can be automatically detected
- (see the documentation on extension for more info).
- </p>
- <source>fopFactory.addElementMapping(myElementMapping); //myElementMapping is a org.apache.fop.fo.ElementMapping</source>
- </li>
- <li>
- <p>
- Set a <strong>URIResolver</strong> for custom URI resolution. By supplying a JAXP URIResolver you can add
- custom URI resolution functionality to FOP. For example, you can use
- <a href="ext:xml.apache.org/commons/resolver">Apache XML Commons Resolver</a> to make use of XCatalogs.
- </p>
- <source>fopFactory.setURIResolver(myResolver); //myResolver is a javax.xml.transform.URIResolver</source>
- <note>
- Both the FopFactory and the FOUserAgent have a method to set a URIResolver. The URIResolver on the FopFactory
- is primarily used to resolve URIs on factory-level (hyphenation patterns, for example) and it is always used
- if no other URIResolver (for example on the FOUserAgent) resolved the URI first.
- </note>
- </li>
- </ul>
- </section>
- <section id="user-agent">
- <title>Customizing the User Agent</title>
- <p>
- The user agent is the entity that allows you to interact with a single rendering run, i.e. the processing of a single
- document. If you wish to customize the user agent's behaviour, the first step is to create your own instance
- of FOUserAgent using the respective factory method on FopFactory and pass that
- to the factory method that will create a new Fop instance:
- </p>
- <source><![CDATA[
- FopFactory fopFactory = FopFactory.newInstance(); //Reuse the FopFactory if possible!
- FOUserAgent userAgent = fopFactory.newFOUserAgent();
- Fop fop = fopFactory.newFop(MimeConstants.MIME_POSTSCRIPT, userAgent);]]></source>
- <p>
- You can do all sorts of things on the user agent:
- </p>
- <ul>
- <li>
- <p>
- The <strong>base URL</strong> to use when resolving relative URLs. Example:
- </p>
- <source>userAgent.setBaseURL("file:///C:/Temp/");</source>
- </li>
- <li>
- <p>
- Set the <strong>producer</strong> of the document. This is metadata information that can be used for certain output formats such as PDF. The default producer is "Apache FOP". Example:
- </p>
- <source>userAgent.setProducer("MyKillerApplication");</source>
- </li>
- <li>
- <p>
- Set the <strong>creating user</strong> of the document. This is metadata information that can be used for certain output formats such as PDF. Example:
- </p>
- <source>userAgent.setCreator("John Doe");</source>
- </li>
- <li>
- <p>
- Set the <strong>author</strong> of the document. This is metadata information that can be used for certain output formats such as PDF. Example:
- </p>
- <source>userAgent.setAuthor("John Doe");</source>
- </li>
- <li>
- <p>
- Override the <strong>creation date and time</strong> of the document. This is metadata information that can be used for certain output formats such as PDF. Example:
- </p>
- <source>userAgent.setCreationDate(new Date());</source>
- </li>
- <li>
- <p>
- Set the <strong>title</strong> of the document. This is metadata information that can be used for certain output formats such as PDF. Example:
- </p>
- <source>userAgent.setTitle("Invoice No 138716847");</source>
- </li>
- <li>
- <p>
- Set the <strong>keywords</strong> of the document. This is metadata information that can be used for certain output formats such as PDF. Example:
- </p>
- <source>userAgent.setKeywords("XML XSL-FO");</source>
- </li>
- <li>
- <p>
- Set the <strong>target resolution</strong> for the document. This is used to
- specify the output resolution for bitmap images generated by bitmap renderers
- (such as the TIFF renderer) and by bitmaps generated by Apache Batik for filter
- effects and such. Default: 72 dpi. Example:
- </p>
- <source>userAgent.setTargetResolution(300); //=300dpi (dots/pixels per Inch)</source>
- </li>
- <li>
- <p>
- Set <strong>your own Renderer instance</strong>. If you want to supply your own renderer or
- configure a Renderer in a special way you can give the instance to the FOUserAgent. Normally,
- the Renderer instance is created by FOP. Example:
- </p>
- <source>userAgent.setRendererOverride(myRenderer); //myRenderer is an org.apache.fop.render.Renderer</source>
- </li>
- <li>
- <p>
- Set <strong>your own FOEventHandler instance</strong>. If you want to supply your own FOEventHandler or
- configure an FOEventHandler subclass in a special way you can give the instance to the FOUserAgent. Normally,
- the FOEventHandler instance is created by FOP. Example:
- </p>
- <source>userAgent.setFOEventHandlerOverride(myFOEventHandler); //myFOEventHandler is an org.apache.fop.fo.FOEventHandler</source>
- </li>
- <li>
- <p>
- Set a <strong>URIResolver</strong> for custom URI resolution. By supplying a JAXP URIResolver you can add
- custom URI resolution functionality to FOP. For example, you can use
- <a href="ext:xml.apache.org/commons/resolver">Apache XML Commons Resolver</a> to make use of XCatalogs.
- </p>
- <source>userAgent.setURIResolver(myResolver); //myResolver is a javax.xml.transform.URIResolver</source>
- <note>
- Both the FopFactory and the FOUserAgent have a method to set a URIResolver. The URIResolver on the FOUserAgent is
- used for resolving URIs which are document-related. If it's not set or cannot resolve a URI, the URIResolver
- from the FopFactory is used.
- </note>
- </li>
- </ul>
- <note>
- You should not reuse an FOUserAgent instance between FOP rendering runs although you can. Especially
- in multi-threaded environment, this is a bad idea.
- </note>
- </section>
- </section>
- <section id="config-external">
- <title>Using a Configuration File</title>
- <p>
- Instead of setting the parameters manually in code as shown above you can also set
- many values from an XML configuration file:
- </p>
- <source><![CDATA[
- import org.apache.avalon.framework.configuration.Configuration;
- import org.apache.avalon.framework.configuration.DefaultConfigurationBuilder;
-
- /*..*/
-
- DefaultConfigurationBuilder cfgBuilder = new DefaultConfigurationBuilder();
- Configuration cfg = cfgBuilder.buildFromFile(new File("C:/Temp/mycfg.xml"));
- fopFactory.setUserConfig(cfg);
-
- /* ..or.. */
-
- fopFactory.setUserConfig(new File("C:/Temp/mycfg.xml"));]]></source>
- <p>
- The layout of the configuration file is described on the <a href="configuration.html">Configuration page</a>.
- </p>
- </section>
- <section id="hints">
- <title>Hints</title>
- <section id="object-reuse">
- <title>Object reuse</title>
- <p>
- Fop instances shouldn't (and can't) be reused. Please recreate
- Fop and FOUserAgent instances for each rendering run using the FopFactory.
- This is a cheap operation as all reusable information is held in the
- FopFactory. That's why it's so important to reuse the FopFactory instance.
- </p>
- </section>
- <section id="awt">
- <title>AWT issues</title>
- <p>
- If your XSL-FO files contain SVG then Apache Batik will be used. When Batik is
- initialised it uses certain classes in <code>java.awt</code> that
- intialise the Java AWT classes. This means that a daemon thread
- is created by the JVM and on Unix it will need to connect to a
- DISPLAY.
- </p>
- <p>
- The thread means that the Java application may not automatically quit
- when finished, you will need to call <code>System.exit()</code>. These
- issues should be fixed in the JDK 1.4.
- </p>
- <p>
- If you run into trouble running FOP on a head-less server, please see the
- <a href="graphics.html#batik">notes on Batik</a>.
- </p>
- </section>
- <section id="render-info">
- <title>Getting information on the rendering process</title>
- <p>
- To get the number of pages that were rendered by FOP you can call
- <code>Fop.getResults()</code>. This returns a <code>FormattingResults</code> object
- where you can lookup the number of pages produced. It also gives you the
- page-sequences that were produced along with their id attribute and their
- number of pages. This is particularly useful if you render multiple
- documents (each enclosed by a page-sequence) and have to know the number of
- pages of each document.
- </p>
- </section>
- </section>
- <section id="performance">
- <title>Improving performance</title>
- <p>
- There are several options to consider:
- </p>
- <ul>
- <li>
- Whenever possible, try to use SAX to couple the individual components involved
- (parser, XSL transformer, SQL datasource etc.).
- </li>
- <li>
- Depending on the target OutputStream (in case of an FileOutputStream, but not
- for a ByteArrayOutputStream, for example) it may improve performance considerably
- if you buffer the OutputStream using a BufferedOutputStream:
- <code>fop.setOutputStream(new java.io.BufferedOutputStream(out));</code>
- <br/>
- Make sure you properly close the OutputStream when FOP is finished.
- </li>
- <li>
- Cache the stylesheet. If you use the same stylesheet multiple times
- you can setup a JAXP <code>Templates</code> object and reuse it each time you do
- the XSL transformation. (More information can be found
- <a class="fork" href="http://www.javaworld.com/javaworld/jw-05-2003/jw-0502-xsl.html">here</a>.)
- </li>
- <li>
- Use an XSLT compiler like <a class="fork" href="http://xml.apache.org/xalan-j/xsltc_usage.html">XSLTC</a>
- that comes with Xalan-J.
- </li>
- <li>
- Fine-tune your stylesheet to make the XSLT process more efficient and to create XSL-FO that can
- be processed by FOP more efficiently. Less is more: Try to make use of property inheritance where possible.
- </li>
- </ul>
- </section>
- <section id="multithreading">
- <title>Multithreading FOP</title>
- <p>
- Apache FOP may currently not be completely thread safe.
- The code has not been fully tested for multi-threading issues, yet.
- If you encounter any suspicious behaviour, please notify us.
- </p>
- <p>
- There is also a known issue with fonts being jumbled between threads when using
- the Java2D/AWT renderer (which is used by the -awt and -print output options).
- In general, you cannot safely run multiple threads through the AWT renderer.
- </p>
- </section>
- <section id="examples">
- <title>Examples</title>
- <p>
- The directory "{fop-dir}/examples/embedding" contains several working examples.
- In contrast to the examples above the examples here primarily use JAXP for
- XML access. This may be easier to understand for people familiar with JAXP.
- </p>
- <section id="ExampleFO2PDF">
- <title>ExampleFO2PDF.java</title>
- <p>This
- <a href="http://svn.apache.org/viewcvs.cgi/xmlgraphics/fop/trunk/examples/embedding/java/embedding/ExampleFO2PDF.java?view=markup">
- example</a>
- demonstrates the basic usage pattern to transform an XSL-FO
- file to PDF using FOP.
- </p>
- <figure src="images/EmbeddingExampleFO2PDF.png" alt="Example XSL-FO to PDF"/>
- </section>
- <section id="ExampleXML2FO">
- <title>ExampleXML2FO.java</title>
- <p>This
- <a href="http://svn.apache.org/viewcvs.cgi/xmlgraphics/fop/trunk/examples/embedding/java/embedding/ExampleXML2FO.java?view=markup">
- example</a>
- has nothing to do with FOP. It is there to show you how an XML
- file can be converted to XSL-FO using XSLT. The JAXP API is used to do the
- transformation. Make sure you've got a JAXP-compliant XSLT processor in your
- classpath (ex. <a href="http://xml.apache.org/xalan-j">Xalan</a>).
- </p>
- <figure src="images/EmbeddingExampleXML2FO.png" alt="Example XML to XSL-FO"/>
- </section>
- <section id="ExampleXML2PDF">
- <title>ExampleXML2PDF.java</title>
- <p>This
- <a href="http://svn.apache.org/viewcvs.cgi/xmlgraphics/fop/trunk/examples/embedding/java/embedding/ExampleXML2PDF.java?view=markup">
- example</a>
- demonstrates how you can convert an arbitrary XML file to PDF
- using XSLT and XSL-FO/FOP. It is a combination of the first two examples
- above. The example uses JAXP to transform the XML file to XSL-FO and FOP to
- transform the XSL-FO to PDF.
- </p>
- <figure src="images/EmbeddingExampleXML2PDF.png" alt="Example XML to PDF (via XSL-FO)"/>
- <p>
- The output (XSL-FO) from the XSL transformation is piped through to FOP using
- SAX events. This is the most efficient way to do this because the
- intermediate result doesn't have to be saved somewhere. Often, novice users
- save the intermediate result in a file, a byte array or a DOM tree. We
- strongly discourage you to do this if it isn't absolutely necessary. The
- performance is significantly higher with SAX.
- </p>
- </section>
- <section id="ExampleObj2XML">
- <title>ExampleObj2XML.java</title>
- <p>This
- <a href="http://svn.apache.org/viewcvs.cgi/xmlgraphics/fop/trunk/examples/embedding/java/embedding/ExampleObj2XML.java?view=markup">
- example</a>
- is a preparatory example for the next one. It's an example that
- shows how an arbitrary Java object can be converted to XML. It's an often
- needed task to do this. Often people create a DOM tree from a Java object and
- use that. This is pretty straightforward. The example here however shows how
- to do this using SAX which will probably be faster and not even more
- complicated once you know how this works.
- </p>
- <figure src="images/EmbeddingExampleObj2XML.png" alt="Example Java object to XML"/>
- <p>
- For this example we've created two classes: ProjectTeam and ProjectMember
- (found in xml-fop/examples/embedding/java/embedding/model). They represent
- the same data structure found in
- xml-fop/examples/embedding/xml/xml/projectteam.xml. We want to serialize a
- project team with several members which exist as Java objects to XML.
- Therefore we created the two classes: ProjectTeamInputSource and
- ProjectTeamXMLReader (in the same place as ProjectTeam above).
- </p>
- <p>
- The XMLReader implementation (regard it as a special kind of XML parser)is
- responsible for creating SAX events from the Java object. The InputSource
- class is only used to hold the ProjectTeam object to be used.
- </p>
- <p>
- Have a look at the source of ExampleObj2XML.java to find out how this is
- used. For more detailed information see other resources on JAXP (ex.
- <a class="fork" href="http://java.sun.com/xml/jaxp/dist/1.1/docs/tutorial/xslt/3_generate.html">An older JAXP tutorial</a>).
- </p>
- </section>
- <section id="ExampleObj2PDF">
- <title>ExampleObj2PDF.java</title>
- <p>This
- <a href="http://svn.apache.org/viewcvs.cgi/xmlgraphics/fop/trunk/examples/embedding/java/embedding/ExampleObj2PDF.java?view=markup">
- example</a>
- combines the previous and the third to demonstrate
- how you can transform a Java object to a PDF directly in one smooth run
- by generating SAX events from the Java object that get fed to an XSL
- transformation. The result of the transformation is then converted to PDF
- using FOP as before.
- </p>
- <figure src="images/EmbeddingExampleObj2PDF.png" alt="Example Java object to PDF (via XML and XSL-FO)"/>
- </section>
- <section id="ExampleDOM2PDF">
- <title>ExampleDOM2PDF.java</title>
- <p>This
- <a href="http://svn.apache.org/viewcvs.cgi/xmlgraphics/fop/trunk/examples/embedding/java/embedding/ExampleDOM2PDF.java?view=markup">
- example</a>
- has FOP use a DOMSource instead of a StreamSource in order to
- use a DOM tree as input for an XSL transformation.
- </p>
- </section>
- <section id="ExampleSVG2PDF">
- <title>ExampleSVG2PDF.java (PDF Transcoder example)</title>
- <p>This
- <a href="http://svn.apache.org/viewcvs.cgi/xmlgraphics/fop/trunk/examples/embedding/java/embedding/ExampleSVG2PDF.java?view=markup">
- example</a>
- shows use of the PDF Transcoder, a sub-application within FOP.
- It is used to generate a PDF document from an SVG file.
- </p>
- </section>
- <section id="example-notes">
- <title>Final notes</title>
- <p>
- These examples should give you an idea of what's possible. It should be easy
- to adjust these examples to your needs. Also, if you have other examples that you
- think should be added here, please let us know via either the fop-users or fop-dev
- mailing lists. Finally, for more help please send your questions to the fop-users
- mailing list.
- </p>
- </section>
- </section>
- </body>
- </document>
|