XMLMill - convert xml to pdf with java. Generate PDF from xml/xsl.

XMLMill for Domino: UseCases

Version: 2.80 Date: November 4th, 2006
This tutorial is opened in a separate window in order to maximize the legibility of this tutorial.
To return to XMLMill, close this browser window

This page as PDFPrinter friendly pageThis guide (!) as PDF

Use case 4: Create different Reminder PDF's per customer based on a Notes-view using XMLMill as a batch-procedure (R5, R6 and R7)

Introduction

In this use case, we have a view of all the invoices which are in status "overdue". We want to create a PDF for every customer in this view. A customer can have different invoices in status "overdue". In this case, we only want 1 PDF for this customer, listing all the invoicedata of the overdue invoices. In the sample of the view you find below, for every customer a reminder must be generated.

images/duremindersview.jpg
Select to enlarge

The PDF-files will be stored in a directory on the filesystem. The shortname of the customer (his customerid) will be used as filename for the PDF. In the Notes-documents a link may be provided to the generated PDF-file on the filesystem.

In order to try out this use case you need following building blocks:

  1. A trial or licensed version of XMLMill for Domino
  2. The Domino Database "XMLMill Domino use cases" (UseCases.nsf), which can be found in the download of XMLMill for Domino.
  3. The Notes-agent GenerateReminders which can be found in the UseCases.nsf
  4. The XSLT-stylesheet remindersshort.xsl
  5. The batch-file reminders.cmd

The result of this use case will be different PDF's organised in the output-directory of the XMLMill-directory. The PDF's consist of a heading containing reminder and customerinformation, a remindertable containing invoice information and some textparagraphs preceding and following the remindertable. A sample of the PDF is shown in the picture below.

images/duremindersshortpdf.jpg
Select to enlarge

A trial or licensed version of XMLMill for Domino

To install XMLMill for Domino, please go to the download page of the XMLMill website and choose the appropriate download distribution (.zip or .tar.gz format)

In case you want to do tests with scheduled agents, extract all the files in the download to a separate subdirectory on the filesystem of your Domino-server or a shared networkdrive on which the Domino-server has read and write access. Make sure that you inherit the directory-structure when you extract the files from your .zip or .tar.gz download to your filesystem.

In case you want to test the use cases locally, extract all the files in the download to a separate subdirectory on your pc. Make sure that you inherit the directory-structure when you extract the files from your .zip or .tar.gz download to your filesystem.

The Domino Database XMLMill Domino use cases

Please refer to the subdirectory domino in the download to find the database Usecases.nsf . Open the database via the Notes-client and locate Use Case 4 - Overdue Invoices in the outline. Activate the view and click on the button Create Reminders. Note however that in order to make the button work correctly, you probably have to modify the paths used in the different building blocks:

  • Check all filepaths used in the Notes-agent GenerateReminders and modify them where necessary.
  • Check all filepaths used in the reminders.cmd and modify them where necessary.

The agent GenerateReminders

You can find the agent GenerateReminders in the Domino-database Usecases.nsf . We will repeat and explain the different parts of this agent below.

The agent opens a file on the filesystem to write the XML-structure to. The view containing all the overdue invoices is traversed and the XML-structure is built. For every customer in the view a PDF will be built. So, a PDF can contain data of different overdue Notes Invoice documents, as long as they belong to the same customer. Then XMLMill-batch is called to transform the XML-file combined with the according XSLT-file into different reminder-PDF's. The PDF's will be written to a subdirectory "reminders" of the output-folder. This directory-structure is defined in the XSLT-stylesheet. The name of the reminder-PDF's will consist of the customerid. We will come back on this later. After XMLMill has generated all PDF's the agent traverses the overdue view again and writes the link to the correct PDF in every Notes-document. The agent consists of following parts:

  1. Initialization of different variables and objects
  2. Get a handle of the first document of the view that will be traversed
  3. Start creating the XML-structure
  4. Traversing through documents in the view
  5. XML-ending tags
  6. Start preparing for XMLMill-batch
  7. Linking to the generated reminder-PDF's in the Notes-documents

Initialization of different variables and objects

[001] Sub Initialize
[002] 	'1) Initializing
[003] 	
[004] 	Dim session As New notessession
[005] 	Dim db As notesdatabase
[006] 	Dim view As notesview
[007] 	Dim doc As notesdocument
[008] 	Dim folder As String
[009] 	Dim invoice As String
[010] 	Dim path As String
[011] 	Dim filename As String
[012] 	Dim filenum As Integer
[013] 	Dim taskId As Integer
[014] 	Dim i As Integer
[015] 	Dim pathName As String
[016] 	Dim rtitem As NotesRichTextItem
[017] 	Dim object As NotesEmbeddedObject	
[018] 	Dim customerid As String
[019] 	Dim reminder As String
[020] 	filenum=1
[021] 	filename= "\\lab_server\xmlmill\domino\reminders.xml"
[022] 	customerid=""
[023] 			

First we initialize the variables and Notes-objects we will need in this script. We define the file that will contain the XML-structure as "\\lab_server\xmlmill\domino\reminders.xml". This file can be placed somewhere on your filesystem, so don't forget to modify the filepath and filename if you want to try this out for your own. Make sure that the user running the agent is able to write to the specified directory on your filesystem. Note that we initialize the variable customerid and assign a blank value to it.

Get a handle of the first document of the view that will be traversed

[001] 
[002]   '2) get a handle of the first document of the view to traverse
[003] 	
[004] 	Set db=session.currentdatabase
[005] 	Set view=db.getview("(LUOverdue)")
[006] 	Set 
       doc=view.getfirstdocument

The view we will loop through in order to build the xml-structure is (LUOverdue). It contains all invoices that are in status "overdue". The view is sorted by customerid and invoicenr. For every customer in this view 1 PDF will be generated. 1 PDF may contain data over different overdue invoice documents.

Start creating the XML-structure

[001] 
[002] ' 3) Start creating xml
[003] 	
[004] 	Print "start creating xml"
[005] 	Open fileName For Output As filenum
[006] 	Print #fileNum, "<?xml version=""1.0"" encoding=""windows-1252"" 
       standalone=""no""?>"
[008] 	Print #filenum,  "<?xml-stylesheet href=""remindersshort.xsl""  
       type=""text/xsl""?>"
[010] 	Print #filenum, ""
[011] 	Print 
       #filenum,"<reminders>"

Before we start looping through the view, we have to open the output file and print the XML file-header to it. Here we can already define the XSLT-stylesheet <?xml-stylesheet href=""remindersshort.xsl"" type=""text/xsl""?> that will be combined with the XML-file. You can also specify the XSLT-stylesheet in the XMLMill batch-file we will discuss later. We also define the opening element of our datastructure <reminders>. This tag contains all PDF's that will be generated.

Traversing through documents in the view

The XML-data we will build while traversing the view has following structure:

[001] <reminders>
[002] 	<reminder>
[003] 		<customerdata>
[004] 			<custid>ALFKI</custid>
[005] 			<company>Alfreds Futterkiste</company>
[006] 			<contact>Maria Anders</contact>
[007] 			<address>Obere Str. 57</address>
[008] 			<zip>12209</zip>
[009] 			<city>Berlin</city>
[010] 			<country>Germany</country>
[011] 		</customerdata>
[012] 		<invoicedata>
[013] 			<nbr>2001-1971</nbr>
[014] 			<date>December 11th. 2001</date>
[015] 			<duedate>January 11th. 2002</duedate>
[016] 			<totalexcl>7784.55</totalexcl>
[017] 			<vat>1634.76</vat>
[018] 			<total>9419.31</total>
[019] 		</invoicedata>
[020] 		<invoicedata>
[021] 			<nbr>2001-1970</nbr>
[022] 			<date>December 11th. 2001</date>
[023] 			<duedate>January 11th. 2002</duedate>
[024] 			<totalexcl>7784.55</totalexcl>
[025] 			<vat>1634.76</vat>
[026] 			<total>9419.31</total>
[027] 		</invoicedata>
[028] 	</reminder>
[029] 	...
[030] </reminders>
  • The information of all PDF documents is contained in the <reminders> and </reminders> elements.
  • The information of 1 PDF document is contained in the <reminder> and </reminder> elements.
  • The invoicedata (invoicenr, invoicetotal,...) can be found in the <invoicedata> and </invoicedata> elements.These tags can be repeated because 1 reminder-PDF can consist of different overdue invoices. The overdue invoices are grouped in 1 PDF per customer.
  • The customerinformation (name, address,..) can be found in the <customerdata> and <customerdata> elements.

This structure is built by the script below. We will explain it after the code:

[001] 
[002] ' 4) traversing through documents in the view
[003] 	
[004] 	While Not doc Is Nothing 
[005] 		
[006] 		If customerid <> doc.custid(0) Then
[007] 		
[008] 			If customerid <> "" Then Print #filenum,"</reminder>"
[009] 			Print #filenum,"<reminder>"
[010] 			Print #filenum,"           <customerdata>"
[011] 			
[012] 			Print #filenum,"             <custid>" + doc.custid(0)+ "</custid>"
[013] 			Print #filenum,"             <company>" + doc.custcompany(0)+ 
         "</company>"
[015] 			Print #filenum,"             <contact>" + doc.custcontact(0)+ 
         "</contact>"
[017] 			Print #filenum,"             <address>" + doc.custaddress(0)+ 
         "</address>"
[019] 			Print #filenum,"             <zip>" + doc.custzip(0)+ "</zip>"
[020] 			Print #filenum,"             <city>" + doc.custcity(0)+ "</city>"
[021] 			Print #filenum,"             <country>" + doc.custcountry(0)+ 
         "</country>"
[023] 			
[024] 			Print #filenum,"           </customerdata>"
[025] 		
[026] 		End If
[027] 		
[028] 		Print #filenum,"           <invoicedata>"
[029] 		
[030] 		Print #filenum,"                <nbr>" + doc.invoicenr(0)+ "</nbr>"
[031] 		Print #filenum,"                <date>" + doc.invoicedate(0)+ "</date>"
[032] 		Print #filenum,"                <duedate>" + doc.invoiceduedate(0)+ 
        "</duedate>"
[034] 		Print #filenum,"                <totalexcl>" + doc.invoicetotalexcl(0)+ 
        "</totalexcl>"
[036] 		Print #filenum,"                <vat>" + doc.invoicetva(0)+ "</vat>"
[037] 		Print #filenum,"                <total>" + doc.invoicetotal(0)+ 
        "</total>"
[039] 		
[040] 		Print #filenum,"           </invoicedata>"
[041] 		
[042] 		customerid=doc.custid(0)
[043] 		Set doc=view.getnextdocument(doc)
[044] 		
[045] 	Wend

During initialization of the variables we assigned the variable customerid a blank value. When we start looping through the view, the first value of the field custid is different from customerid, so we know we have a new customer and we have to create a new reminder by opening the <reminder> element. Because the last known value of customerid is blank, we know we are dealing with the first document and we don't have to close a preceding tag.

If we are starting the first reminder, we have to capture the customerdata together with invoice information of 1 or more invoices. The structure of the <customerdata> element is fairly simple. In this tag, we capture the relevant field information such as customerid ("<custid>" + doc.custid(0)+ "</custid>" ), companyname ("<company>" + doc.custcompany(0) + "</company>"),.. Next we add the invoice information by opening the <invoicedata> element and its descendants: invoicenumber ("<nbr>" + doc.invoicenr(0) + "</nbr>"), invoicetotal ("<total>" + doc.invoicetotal(0) + "</total>"),...

Before we move on to the next document in the view, we assign the variable customerid the value of the customerid of the current (first) document.

The next document of the view may belong to the same or a different customer as the previous (first) one.

If the current overdue invoice belongs to the same customer as the previous one, we only have to capture the current invoiceinformation by adding the <invoicedata> element and its descendants. Note that in the above script, the customerdata elements are only used if the current customerid differs from the previous one (If customerid <> doc.custid(0) Then .... script to add customerinfo )

If the current overdue invoice belongs to a different customer than the previous one, we have to carry out different steps:

  • Since the current invoice belongs to a new customer, we have to create a new reminder. Before this, we must close the preceding reminder by adding the </reminder>-closing tag. Next we open the new reminder by the <reminder>-opening tag.
  • A new customer also means that we have to capture the customerinformation, so we append the <customerdata> element and its descendants.
  • Next, as for every overdue invoice, we capture the invoiceinformation, so we append the <invoicedata> element and its descendants.

Before we move on to the next document in the view, we assign the variable customerid the value of the customerid of the current document.

The preceding steps are repeated for all documents in the overdue-view.

XML ending tags

[001] 
[002] '5) xml-closing tags
[003] 	Print #filenum,"</reminder>"
[004] 	Print #filenum,"                     </reminders>"
[005] 	Close fileNum	

When the last document has been processed, the remaining opened tag are closed by adding:</reminder> and </reminders>. The file is closed and ready to be processed by XMLMill.

Start preparing for XMLMill-batch

[001] 
[002] '6) Start preparing for xml-batch
[003] 	
[004] pathName$ = "\\lab_server\xmlmill\domino\output\ended.txt"
[005] If  Dir$(pathName$, 0) <> "" Then Kill pathname$
[006] taskId% = Shell("\\lab_server\xmlmill\domino\reminders.cmd", 1)
[007] 	
[008] Do While Dir$(pathName$, 0)= ""
[009] Loop
[010] 
[011] Kill 
      pathname$	

After generating the reminder PDF's, we want the agent to capture the PDF-files and create a link to them in the correct Notes-document. Therefore we need a means to know when the PDF-files are ready. This is why we introduce a small text-file ended.txt. When this file is present, this means the PDF's are ready and the agent may proceed. So before we call XMLMill, we first test if this file is already on the filesystem. If it is, we delete it:

[001] If  Dir$(pathName$, 0) <> "" Then Kill 
      pathname$

Then XMLMill is called outside the Domino-environment. Therefore we issue a shell-command:

[001] taskId% = Shell("\\lab_server\xmlmill\domino\reminders.cmd", 1) 

It will start the batch-file as a normal (not minimized) window with focus. If you want to run the batch-file minimized without focus, use 6 or 7 instead of 1. After generating the PDFs, the batch-file executes a command which copies a little text-file starting.txt to another file ended.txt.

The agent was waiting for the ended.txt. As long as this file isn't available on the filesystem, the agent loops. If the file is available, the agent deletes the file again and moves on.

If you try this example, do not forget to alter your path to point to the right directory on your filesystem. We will come back on the content of the reminders.cmd in the next sections.

Linking to the generated reminder-PDF's in the correct Notes-documents

[001] '7) Linking PDF in Notes- invoice documents
[002] 	
[003] Set doc=view.getfirstdocument
[004] 	
[005] While Not doc Is Nothing
[006]  reminder=doc.custid(0)
[007]  path="\\lab_server\xmlmill\domino\output\reminders\" + reminder + ".pdf" 
       
[009] 
[010] 	If  Dir$(path, 0) <> "" Then
[011] 			
[012]     doc.pdflink="file:\\lab_server\xmlmill\domino\output\reminders\" 
          +reminder+ ".pdf"
[014] 	 Call doc.save(True,False)
[015] 	
[016] 	End If
[017] 
[018] Set doc=view.getnextdocument(doc)
[019] Wend
[020] end 
      sub

After the generation of the reminder-PDF's, we want to create a link to them in the correct Notes-documents. After the link is provided, the Notes-documents will look like this:

images/dureminderspdfcontainer.jpg
Select to enlarge

In order to capture the PDF-files on the filesystem, we start by traversing the view ("(LUOverdue)") for the second time. For each Notes-document, we know where to expect the corresponding PDF-file: it is generated in the subdirectory reminders of the output-folder output and the filename consists of the customerid. So for each Notes-document, we can build the path to the generated PDF by the script:

[001] reminder=doc.custid(0)
[002] path="\\lab_server\xmlmill\domino\output\reminders\" + reminder + ".pdf" 
[003] 	

Next we check if the PDF is present and if so we create a link to the PDF-file in the current Notes-document. We define a text-field PDFLink and fill it with the filepath of the PDF-file on the filesystem. In the Notes-document there is a button next to the field, invoking a urlopen-command on the value of the PDFLink-field. Note that different Notes-documents may link to the same PDF-file.

The XSLT-stylesheet remindersshort.xsl

Overview

In order to transform the XML-datastructure in this use case, a stylesheet has been created which can be found in the domino/ directory in the download.

Please open the remindersshort.xsl in your xml-editor when you go through this chapter.

In the next sections an overview about the most important elements is given.

In the XSLT-stylesheet, you will find instruction elements to generate each of the parts. These instruction elements are grouped in templates. These templates are called either by <xsl:call-template name="..."> or by <xsl:apply-templates select="...">.

The global structure of the remindersshort.xsl can be summarized as follows:

[001] 
[002] <?xml version="1.0" encoding="UTF-8"?>     
[003]   <xsl:stylesheet 
[004]     xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
[005]     xmlns:ml="http://www.xmlmill.com/XSL/Format" 
[006]     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
[007]     xsi:schemaLocation="http://www.xmlmill.com/XSL/Format xmlmill.xsd"
[008]     version="1.0" >
[009]   <xsl:template match="/">
[010]     <ml:documents>
[011]       <xsl:for-each select="reminders/reminder">
[012]         <ml:document>
[013]           <xsl:call-template name="print-info"/>
[014]           <xsl:call-template name="print-pagetemplate"/>
[015]           <xsl:call-template name="print-content"/>
[016]         </document>
[017]       </xsl:for-each>
[018]     </ml:documents>
[019]   </xsl:template>
[020] 
[021]     <xsl:template name="print-info">
[022]   ...
[023]   </xsl:template>
[024]   
[025]     <xsl:template name="print-pagetemaplate">
[026]   ...
[027]   </xsl:template>  
[028]   
[029]     <xsl:template name="print-content">
[030]   ...
[031]   </xsl:template>  
[032] 
[033]     <xsl:template name="print-reminderheader">
[034]   ...
[035]   </xsl:template>  
[036]   
[037]     <xsl:template name="print-reminderbody">
[038]   ...
[039]   </xsl:template>    
[040] 
[041] </xsl:stylesheet>

The <?xml?> prolog

The prolog is the first line of a xml document defining the encoding of the document:

[001] <?xml version="1.0" 
      encoding="UTF-8"?>

This is important as you need an editor that supports the specified encoding in order to correctly see the content of the document and write any changes back in the correct encoding (the one defined here). If the encoding is UTF-8 and you edit the xml document with a editor that only supports ASCII you will see 'strange' characters.

  • It is strongly recommended to use a xml-editor which supports different encodings.

The <xsl:stylesheet> element

The <xsl:stylesheet> element defines a reference to the ml: namespace that contains all valid XMLMill elements and their attributes.

[001] 
[002] <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
[003]                 xmlns:ml="http://www.xmlmill.com/XSL/Format" 
[004]                 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
[005]                 xsi:schemaLocation="http://www.xmlmill.com/XSL/Format 
                      xmlmill.xsd" 
[007]                 version="1.0" >
[008]   <xsl:output method="xml" indent="yes" encoding="UTF-16"/>     
[009]   <xsl:output/>
[010]   <xsl:decimal-format decimal-separator="," grouping-separator="."/> 
[011]   ...
[012]           

1

Define the ml: namespace by referring to the correct namespace name. In this case the namespace name is a URI mapping to: http://www.xmlmill.com/XSL/Format.

2

Define an instance of a XMLSchema.

3

Define where the instance of the XMLSchema is located. The XMLSchema is referenced using the namespace name (http://www.xmlmill.com/XSL/Format). The second parameter (xmlmill.xsd) defines the actual location and name of .xsd schema.

4

When the xml document is transformed with the xsl stylesheet, an internal .mill document is generated, used to generate the .pdf document. The <output> element defines the characteristics of this intermediate .mill file.

5

Optionally the decimal symbol is defined as ',' and the thousands-grouping-separator is defined as '.' in the <xsl:decimal-format> element.

  • The docs/xsd/ directory contains a default xsl stylesheet and the xmlmill.xsd and xslt.xsd file. Please keep these two files in the same directory as the xslt.xsd file is referenced in the xmlmill.xsd file.

The <ml:documents> element

The processing of the stylesheet always start at the expression <xsl:template match="/">.

[001] <xsl:template match="/">
[002] <ml:documents whitespace-collapse="on" >
[003]   <xsl:for-each select="reminders/reminder">
[004]     <ml:document>
[005]       <xsl:attribute name="file">
[006]       output\reminders\<xsl:value-of 
            select="customerdata/custid"/>.pdf</xsl:attribute>
[008]       <xsl:call-template name="print-info"/>
[009]       <xsl:call-template name="print-pagetemplate"/>
[010]       <xsl:call-template name="print-content"/>
[011]     </ml:document>
[012]   </xsl:for-each>
[013] </ml:documents>
[014] </xsl:template>

First the <mldocuments> element is processed. The whitespace-collapse is set to "on" meaning that the sequences of whitespace characters in the XML-file are reduced to 1 single whitespace character.

Next the for-each loop is executed in order to iterate over the different reminder-branches. This is done by the <xsl:for-each>-element:

[001] <xsl:for-each select="reminders/reminder">
[002]           ...
[003] </xsl:for-each>

For every reminders/reminder-branch in the XML-file a new PDF has to be created and a filename must be provided. This is done by opening the <ml:document> element and assigning the attribute file the value of the filename. We want to generate the filename dynamically: it will be saved in a subdirectory of the outputdirectory of XMLMill: reminders. We capture the value of the filename by the instruction element: <xsl:value-of select="customerdata/custid"/>. So the customerid can be found in the XML-file on the branch customerdata/custid. This value is then used to form the entire path: output\reminders\custid.pdf. The entire instruction looks like this:

[001] <ml:document>
[002]   <xsl:attribute name="file">output\
[003]   <xsl:value-of select="customerdata/custid"/>.pdf</xsl:attribute>

Further remaining instruction elements are grouped in templates. They are called from within the <ml:document> element or from within a template called by the <ml:document> element. The templates which are directly called from within the <ml:document> element are:

  • Template "print-info"
  • Template "print-pagetemplate"
  • Template "print-content"

Deze templates together with their dependents are processed. We will explain them in the next sections.

Processing so far is repeated for every reminder. After the processing rules, the remaining opened tags are closed:

[001] </ml:document>
[002]   </xsl:for-each>
[003]     </documents>
[004]   
        </xsl:template>

The <ml:document> element

From within the <ml:document> element grouped instruction elements called templates are executed. They can be called either directly from the <ml:document> element or nested from within a called template. These templates will build the different elements of the PDF:

  • The template print-info is called from within the <document> element and defines the indexing properties of the PDF.
  • The template print-pagetemplate is called from within the <document> element and defines the general page-layout of the PDF such as the header and footer. Here the Magnolia Hall logo in the header will be defined.
  • The template print-content is called from within the <document> element and defines the entire content of the PDF. This content is built by 2 other templates print-reminderheader and print-reminderbody.
  • The template print-reminderheader is called from within the print-content-template and defines the table containing the reminder and customer information and the red horizontal line.
  • The template print-reminderbody is also called from within the print-content-template and defines the standard text paragraphs and the table containing the invoice information. This template will also call the template lines used to iterate over the different overdue invoices.
  • From within the print-reminderbody template lines is called. This template contains the instruction elements that build the different lines in the table of overdue invoices.

The relations between the different templates is summarized in the picture below.

images/duremindersshort.jpg
Select to enlarge

In the next sections we will elaborate on these different templates.

Template "print-info"

The first template which is called from within the <document> element is the template "print-info".

[001] <xsl:template name="print-info">
[002]   <ml:meta-info>
[003]     <ml:meta-title>Reminders</ml:meta-title>
[004]     <ml:meta-subject>Reminders</ml:meta-subject>
[005]     <ml:meta-author>xmlmill</ml:meta-author>
[006]     <ml:meta-keywords>www.xmlmill.com</ml:meta-keywords>
[007]   </ml:meta-info>
[008] </xsl:template>

The <ml:meta-info> element is a child of the <ml:document> element. Here we define the indexing information that can be found in the properties of the PDF. In the PDF you must choose "File-Document Info - General" to view these properties. We specify the title, the subject, the author and some keywords for the PDF.

Template "print-pagetemplate"

The second template which is called from within the <ml:document> element is the template "print-pagetemplate".

[001] <xsl:template name="print-pagetemplate">
[002]     <ml:layout-master-set>
[003]       <ml:simple-page-master master-name="content-pages" ...>
[004]         <ml:region-body column-count="1" .../>
[005]         <ml:region-before .../>
[006]         <ml:region-after .../>
[007]         <ml:region-start .../>
[008]         <ml:region-end .../>
[009]       </ml:simple-page-master>
[010]     </ml:layout-master-set>
[011] </xsl:template>

The <ml:layout-master-set> element contains ml:simple-page-master element(s) which define the page-layout of the page where this <ml:layout-master-set> is applied to (referenced by the <ml:page-sequence>).

A page can contain up to five 'regions', of which 3 are mostly used:

<ml:region-before>

The upper region on the page (mainly used to define the 'header' of a page).

<ml:region-body>

This is the center region on the page to define the content of a page.

<ml:region-after>

The bottom region on the page (mainly used to define the 'footer' of a page).

  • For more information regarding these elements please visit the dtdguide.pdf document contained in the docs/ directory in the download.(
  • Also visit the examples in the samples/mill and samples/xmlxsl directory to consult how these elements can be used.

Template "print-content"

The third template which is called from within the <ml:document> element is the template "print-content", with following content structure:

[001] 
[002]   <xsl:template name="print-content">
[003]     <ml:page-sequence initial-page-number="1" 
          master-reference="content-pages">
[005]       <ml:static-content flow-name="xsl-region-before">
[006]         <ml:external-graphic src="images\magnolia.jpg" .../>
[007]       </ml:static-content>
[008]       <ml:static-content flow-name="xsl-region-after">
[009]         <ml:textbox valign="top" ... >8515 Haven Wood Trail - Roswell, GA 
              30076 </ml:textbox>
[011]         <ml:textbox valign="top" ... >
[012]           <ml:page-number/>
[013]         </ml:textbox>
[014]       </ml:static-content>
[015]       <ml:flow flow-name="xsl-region-body">
[016]         <xsl:call-template name="print-reminderheader"/>
[017]         <xsl:call-template name="print-reminderbody"/>
[018]       </ml:flow>
[019]     </ml:page-sequence>
[020]   </xsl:template>          

The <page-sequence> element contains the content of the pages to generate. It contains two important elements:

<ml:static-content>

This element defines the content that should be repeated on each page (like a header of footer). THe flow-name refers to a region defined in the simple-page-master that is referenced by the master-reference attribute in the parent <ml:page-sequence>.

<ml:flow>

This element defines the 'flowing' content of a pages, adding new pages to the document if needed.

The bulk of the elements will be children of the <ml:flow> element describing the content of a page (and subsequent page if the content does not fit in one page).

The <ml:flow> calls following templates:

  1. The instruction element <xsl:call-template name="print-reminderheader"/> calls the template responsible for building the table containing the reminderinfo and the customerinfo. The reminder date is placed to the left of the table. The customerinfo (address information) is placed to the right of the table.
  2. The instruction element <xsl:call-template name="print-reminderbody"/> calls the template responsible for building the table containing the different invoicelines. The template starts with some standard text-paragraphs. Next, the headerrow of the invoicetable is built. After the headerrow an iteration is invoked (<xsl:for-each select="invoicedata">) to process every invoiceline (<xsl:call-template name="lines">). After the processing of the invoicelines some standard textparagraphs are inserted to conclude the reminder.

These templates will call other templates:

  • print-reminderheader
  • print-reminderbody
  • lines

Please study the content of the templates to know how the document is generated.

  • For more information regarding these elements please visit the dtdguide.pdf document contained in the docs/ directory in the download.(
  • Also visit the examples in the samples/mill and samples/xmlxsl directory to consult how these elements can be used.

The XMLMill batch-file reminders.cmd

The XMLMill batch-file calls XMLMill outside the Domino-environment and tells the system where to find XMLMill and the required XML- and XSLT-files. To try out this example, you should:

  • modify the products.cmd file, so that 1) the classpath points to the directory where you installed XMLMill and 2) all required jar-files are included.
  • make sure the JAVA_HOME variable points to the directory where your java.exe resides.
  • use the correct parameters (see below) so that the correct xml-file and XSL-file are used.

Please find below an overview of a sample batch file:

[001] @echo off
[002] REM -------------------
[003] REM -- XMLMILL BATCH --
[004] REM -------------------
[005] 
[006] REM PLEASE ADAPT CLASSPATH TO INCLUDE JAR FILEs CORRECLY.
[007] REM PLEASE ADAPT DIR POINTING TO JAVA.EXE.
[008] 
[009] set JAVA_HOME="\\labserver\progs\JavaSoft\JRE\1.3.1\bin\java"
[010] set CLASSPATH=\\lab_server\xmlmill\lib\sun-xercesImpl.jar
[011] set CLASSPATH=%CLASSPATH%;\\lab_server\xmlmill\lib\sun-xalan.jar
[012] set CLASSPATH=%CLASSPATH%;\\lab_server\xmlmill\lib\sun-jaxp-api.jar
[013] set CLASSPATH=%CLASSPATH%;\\lab_server\xmlmill\lib\sun-sax.jar
[014] set CLASSPATH=%CLASSPATH%;\\lab_server\xmlmill\lib\sun-dom.jar
[015] set CLASSPATH=%CLASSPATH%;\\lab_server\xmlmill\lib\xmlmill.jar
[016] set CLASSPATH=%CLASSPATH%;\\lab_server\xmlmill\lib\log4j.jar
[017] @echo on
[018] %JAVA_HOME% com.xmlmill.batch.Main  -m 
      \\lab_server\xmlmill\domino\reminders.xml -s 
      \\lab_server\xmlmill\domino\remindersshort.xsl -l reminders.log -v
[021] 
[022] copy \\lab_server\xmlmill\domino\output\starting.txt 
      \\lab_server\xmlmill\domino\output\ended.txt 

Note that instructions beginning with REM are not executed.

The script calls Java and the com.xmlmill.batch.Main class with the appropriate flags and arguments. You find the command line that processes the products XML- and XSLT-file below:

[001] %JAVA_HOME% com.xmlmill.batch.Main  -m 
      \\lab_server\xmlmill\domino\reminders.xml -s 
      \\lab_server\xmlmill\domino\remindersshort.xsl -l reminders.log -v

The used flags are explained below:

-v

Enable verbose output.If this flag is omitted, no messages will be printed to the console.

-m

Defines the XML-file or directory containing XML files. Multiple -m files can be defined.

-s

Defines the XSLT-file that will be used to transform the XML-file(s). If specified this .XSL file will overrule any .XSL file defined in the .XML file (defined in the <?xml-stylesheet ...?> tag).

-l

Defines the (existing) logfolder and/or logfile name. If a filename is defined it should end with .log. If the log-folder only contains a filename (ending in .log), the log will be written in the directory of the first xml-file that is processed. If no log-file is defined, all log messages (if any) will be send to the screen.

-o

Defines the (existing) outputfolder. If no outputfolder is defined, the output will be written in the directory defined by file attribute of the <output> tag of the first XML-file processed.

Copyright © 2001 - 2012. All rights reserved. XMLMill and XMLMill logo are trademarks of Pecunia Data Systems, bvba.
Powered by Apache CocoonPowered by XMLMill