Click here to Skip to main content
12,747,862 members (39,627 online)
Click here to Skip to main content
Add your own
alternative version


50 bookmarked
Posted 30 Jul 2013

Creating PDF documents from XML

, 16 Aug 2013 CPOL
Rate this:
Please Sign up or sign in to vote.
Creating PDF documents from XML


This article is about using XML/XSL-FO and the open source library FO.NET to generate PDF documents by mixing input parameters, images and static localization strings. I think that this kind of approach is ideal to automate the process of generating invoices or simple dynamic documents/reports related to web service/server pages input parameters.  


The following image describes the idea behind this solution: 

The user submits its request to the web service. The request is serialized to XML and merged with a static localization XML. The result is passed through an XSLT sheet and the output is an XSL-FO document. XSL-FO ( is a language for formatting XML data for output to screen, paper or other media. It can be parsed by FO.NET ( in order to produce PDF documents. 

Architecture overview

 The following UML diagram represents the relationships among the most important classes in the solution.


A short description of each class and of their responsibilities: 

  • IPdfPrintableDocument: represents a basic interface for a PDF printable document.
  • Document: represents a really simple printable document.
  • XmlTransformationManager: gets the printable document instance and merges it with the related XML culture file. The output is a new XML file that is passed through the related XSLT file. The final output is an XSL-FO document that can be parsed by FO.NET.
  • PdfPrinterDriver: handles the PDF generation process with the help of the FonetDriver class.
  • ResourceManager: it is responsible to access the localization and transformation files. It makes use of the CacheUtility class to store retrieved files in cache in order to speed up the execution of subsequent requests 
  • CacheUtility: a simple wrapper for System.Web.Caching.Cache class   



In the web.config there is a little configuration section: 

  • xsltFolderPath: tells the application where to find the XSLT files.
  • localizationXmlFolderPath: tells the application where to find the localization files.
  • defaultCulture: default application culture.
  • defaultDateFormat: DateTime format.
  • pdfOutputFolder: tells the application where to save PDF files.  

Creating a simple WCF Service  

I decided to test the PDF printer core with a simple WCF service. First of all let's create an IPrintableDocument class

[Serializable, DataContract(Namespace = "http://Schemas/PdfPrinter/Common")]
public class Document : IPrintableDocument
    [DataMember(IsRequired = true)]
    public string Description;
    public string ToXml()
        return ObjectXmlSerializer.SerializeObjectToXmlFormattedString(this);

Then let's write out simple web service with request and response 

[ServiceBehavior(Namespace = "http://Schemas/PdfPrinter/WebServices")]
public class PdfPrinterService : IPdfPrinter
    public PdfPrinterResponse Print(PdfPrinterRequest request)
        return PdfPrinterFacade.PrintPdf(request);
public class PdfPrinterResponse
    public string Info;
    public string Message;        
public class PdfPrinterRequest
    private Document _document;
    public Document Document
        get { return _document; }
        set { _document = value; }

Finally let's implement our XSLT and localization XML files and name them as Document class. 

I put Document.xslt under "~/App_Data/Resources/XSLT/" folder. This is a simple XSLT that shows some powerful features of XSL-FO. Then I wrote a simple localization XML file Document.xml and I put it under  "~/App_Data/Resources/XML/" folder.  

Running the code 

Let's invoke out web service with Document.Description = "Hello". 

All input data is merged within an XML document that looks like this 

  <culture language="en-US">
    <label id="Footer" text="This documents has been auto-generated with Pdf Printer Service"/>
    <label id="Page" text="Page " />
    <label id="Of" text=" of " />
    <label id="Message" text="You sent the following message:" />
    <label id="EmptyMessage" text="- Empty message -" />
    <label id="Date_Header_1" text="Date" />
    <label id="LongWord_Header_2" text="Very Long Word" />
    <label id="Decimal_Header_3" text="Decimal" />
    <label id="Integer_Header_4" text="Integer" />
    <label id="Total" text="Total" />
    <label id="Date_Field_1" text="11/02/1984" />
    <label id="LongWord_Field_2" text="ThisIsAVeryVeryLongBreakedWord" />
    <label id="Decimal_Field_3" text="1234.5678" />
    <label id="Integer_Field_4" text="3" />

Then the XSLT file produces the XSL-FO document by querying previous XML content. It makes use of an helper extension class (PdfPrinter.Core.Common.XsltExtensionService) which simplifies some common operations.  

. . .
<xsl:variable name="logo" 
   <fo:external-graphic src="url('{$logo}')" 
        content-width="auto" content-height="auto"/>
   <fo:block padding-top="2pt">
   <fo:block text-align="left" font-size="16pt">
   <fo:inline font-weight="bold">
   <xsl:value-of select="/PdfPrinter/culture/label[@id='Message']/@text"/>
   <fo:block text-align="left" padding-top="2pt" font-size="16pt">
   <xsl:when test="/PdfPrinter/Document/Description != ''">
   <xsl:value-of select="/PdfPrinter/Document/Description"/>
   <xsl:value-of select="/PdfPrinter/culture/label[@id='EmptyMessage']/@text"/>
. . . 

The final result is parsed by FO.NET and the output looks really great!


The benefit of generating PDF documents with this approach is that the developer doesn't have to know any particular API and can modify at runtime the document layout just by changing some XSLT queries or adding new XSL-FO statements.

I hope that my work will be helpful and enjoyable to use! 


This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


About the Author

Marco Merola
Software Developer
Italy Italy
Take a look at my professional profile and become a part of my network on LinkedIn.

You may also be interested in...


Comments and Discussions

QuestionHow to have multiple classes in PdfPrinterRequest class to generate multiple different reports Pin
maruthipuligandla14-Jul-16 22:33
membermaruthipuligandla14-Jul-16 22:33 
QuestionHow to maintain more than one XSL template and dynamic XML instead of XML file Pin
maruthipuligandla10-Jul-16 23:26
membermaruthipuligandla10-Jul-16 23:26 
AnswerRe: How to maintain more than one XSL template and dynamic XML instead of XML file Pin
Marco Merola14-Jul-16 9:07
memberMarco Merola14-Jul-16 9:07 
GeneralRe: How to maintain more than one XSL template and dynamic XML instead of XML file Pin
maruthipuligandla14-Jul-16 18:04
membermaruthipuligandla14-Jul-16 18:04 
QuestionUsing the PdfPrinterCore along with WinForms Pin
Member 1247287423-Jun-16 1:19
memberMember 1247287423-Jun-16 1:19 
AnswerRe: Using the PdfPrinterCore along with WinForms Pin
Marco Merola14-Jul-16 9:00
memberMarco Merola14-Jul-16 9:00 
QuestionHow to make columns dynamically fetch from the XML Pin
maruthipuligandla20-Jun-16 18:54
membermaruthipuligandla20-Jun-16 18:54 
AnswerRe: How to make columns dynamically fetch from the XML Pin
Marco Merola21-Jun-16 9:38
memberMarco Merola21-Jun-16 9:38 
GeneralRe: How to make columns dynamically fetch from the XML Pin
maruthipuligandla21-Jun-16 17:10
membermaruthipuligandla21-Jun-16 17:10 
GeneralRe: How to make columns dynamically fetch from the XML Pin
maruthipuligandla21-Jun-16 19:28
membermaruthipuligandla21-Jun-16 19:28 
GeneralRe: How to make columns dynamically fetch from the XML Pin
Marco Merola14-Jul-16 8:54
memberMarco Merola14-Jul-16 8:54 
GeneralRe: How to make columns dynamically fetch from the XML Pin
maruthipuligandla14-Jul-16 18:01
membermaruthipuligandla14-Jul-16 18:01 
GeneralMy vote of 3 Pin
Member 123148718-Feb-16 12:10
memberMember 123148718-Feb-16 12:10 
GeneralMy vote of 5 Pin
Jeremy Njoroge29-Oct-15 20:44
memberJeremy Njoroge29-Oct-15 20:44 
QuestionGenerating the xsl-fo file Pin
Member 117881655-Jul-15 23:43
memberMember 117881655-Jul-15 23:43 
AnswerRe: Generating the xsl-fo file Pin
Marco Merola6-Jul-15 8:08
memberMarco Merola6-Jul-15 8:08 
QuestionXSL-FO Pin
Member 1139185319-Feb-15 6:24
memberMember 1139185319-Feb-15 6:24 
AnswerRe: XSL-FO Pin
Marco Merola11-Apr-15 1:59
memberMarco Merola11-Apr-15 1:59 
AnswerRe: XSL-FO Pin
Marco Merola11-Apr-15 2:08
memberMarco Merola11-Apr-15 2:08 
Questioncustom xml Pin
sasi rekha29-Jan-15 16:45
membersasi rekha29-Jan-15 16:45 
AnswerRe: custom xml Pin
Marco Merola11-Apr-15 1:54
memberMarco Merola11-Apr-15 1:54 
QuestionCreate PDF document Pin
smithjimmy5-Nov-13 20:44
membersmithjimmy5-Nov-13 20:44 
QuestionSource code doesn't generate PDF Pin
deepika bandi23-Oct-13 21:49
memberdeepika bandi23-Oct-13 21:49 
AnswerRe: Source code doesn't generate PDF Pin
Marco Merola1-Nov-13 6:41
memberMarco Merola1-Nov-13 6:41 
GeneralMy vote of 5 Pin
Burak Ozdiken1-Aug-13 20:16
memberBurak Ozdiken1-Aug-13 20:16 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Terms of Use | Mobile
Web01 | 2.8.170215.1 | Last Updated 16 Aug 2013
Article Copyright 2013 by Marco Merola
Everything else Copyright © CodeProject, 1999-2017
Layout: fixed | fluid