I have a project where the client wants to supply PDF documents from an XML dataset. I have worked with XSLT many years, but never created a PDF. I have generated new XML and HTML using XSLT, but never a PDF.
Asked
Active
Viewed 664 times
1
-
1There's this [question](http://stackoverflow.com/q/212577/229858) that may help. – Dave M Mar 31 '12 at 03:00
-
@DaveM Good link Dave - I failed to notice your comment when I formulated my answer! – Maestro13 Mar 31 '12 at 08:51
-
You could use Online Api http://www.convertapi.com – Tomas Apr 01 '12 at 17:25
-
Thanks for your replies. I have been working on other projects in the meantime. I will check your answers to see if they work in my project. We are looking at a JavaScript + XML approach right now, which seems easier to accomplish. Thanks. – Jim Maivald Jun 14 '12 at 03:03
2 Answers
3
You will have to do a two-step approach, first applying an xsl-fo transformation, creating specific fo tags, then run it by a fo to pdf process.
Below is a piece of VB code that I use for this, plus a small piece of my xsl-fo.
'Transform to create fo file
foName = "C:\test\foName_test.fo"
xslName = "C:\test\xhtml2fo.xslt"
Call Transform(flName, xslName, foName)
'Call FOP PDF generator
Set shell = CreateObject("WScript.Shell")
pdfName = "C:\test\foName_test.pdf"
cmd = "java -Dfop.home=C:\fop -cp C:\fop\build\fop.jar org.apache.fop.cli.Main -fo " & foName & " -pdf " & pdfName
Call shell.Run(cmd, vbWindowFrame, True)
Private Sub Transform(sourceFile, stylesheetFile, resultFile)
Dim source As New MSXML2.DOMDocument60
Dim stylesheet As New MSXML2.DOMDocument60
Dim result As New MSXML2.DOMDocument60
Dim objStream As New ADODB.Stream
Dim msg As String
objStream.Open
objStream.Position = 0
objStream.Charset = "utf-8"
objStream.LoadFromFile (sourceFile)
' Load data
source.async = False
source.loadXML (objStream.ReadText())
' Load style sheet
stylesheet.async = False
stylesheet.Load stylesheetFile
' Do the transform
source.transformNodeToObject stylesheet, result
result.Save resultFile
End Sub
XSLT code snippet:
<xsl:template name="make-layout-master-set">
<fo:layout-master-set>
<fo:simple-page-master master-name="all-pages" xsl:use-attribute-sets="page">
<fo:region-body margin-top="{$page-margin-top}" margin-right="{$page-margin-right}" margin-bottom="{$page-margin-bottom}" margin-left="{$page-margin-left}" column-count="{$column-count}" column-gap="{$column-gap}"/>
<xsl:choose>
<xsl:when test="$writing-mode = 'tb-rl'">
<fo:region-before extent="{$page-margin-right}" precedence="true"/>
<fo:region-after extent="{$page-margin-left}" precedence="true"/>
<fo:region-start region-name="page-header" extent="{$page-margin-top}" writing-mode="lr-tb" display-align="before"/>
<fo:region-end region-name="page-footer" extent="{$page-margin-bottom}" writing-mode="lr-tb" display-align="after"/>
</xsl:when>
<xsl:when test="$writing-mode = 'rl-tb'">
<fo:region-before region-name="page-header" extent="{$page-margin-top}" display-align="before"/>
<fo:region-after region-name="page-footer" extent="{$page-margin-bottom}" display-align="after"/>
<fo:region-start extent="{$page-margin-right}"/>
<fo:region-end extent="{$page-margin-left}"/>
</xsl:when>
<xsl:otherwise><!-- $writing-mode = 'lr-tb' -->
<fo:region-before region-name="page-header" extent="{$page-margin-top}" display-align="before"/>
<fo:region-after region-name="page-footer" extent="{$page-margin-bottom}" display-align="after"/>
<fo:region-start extent="{$page-margin-left}"/>
<fo:region-end extent="{$page-margin-bottom}"/>
</xsl:otherwise>
</xsl:choose>
</fo:simple-page-master>
</fo:layout-master-set>
</xsl:template>