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 2: Create a PDF with bookmarks and a table of content based on a Notes-view using XMLMill as a batch-procedure (R5, R6 and R7)

Introduction

In this use case, we have a list of all our products we buy with certain suppliers. Every product belongs to a certain product family and has a name, weight, price, expiration date and serialnumber. For every productfamily we can have one or more suppliers. We want to create a PDF on a daily basis providing us the list of our products sorted by supplier and product family. The PDF must contain bookmarks in the navigation pane and a table of content on top of the list. After creation the PDF may be attached to a Notes-document acting as a PDF container, so that the users can download the PDF-file.

images/duproductsview.jpg
Select to enlarge

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 Usecases" (UseCases.nsf), which can be found in the download of XMLMill for Domino.
  3. The Notes-agent ProductList which can be found in the UseCases.nsf
  4. The XSLT-stylesheet productsshort.xsl
  5. The Batch-file products.cmd

The result of this use case will be a PDF with a table of content and an outline in the bookmarkbar. Every supplier begins at a new page and for every productfamily there is a table containing all the products of that productfamily. A sample of the PDF is shown in the picture below. Keep in mind, that when you try out the use cases with the trial version, you will only see 2 pages of the entire PDF. Although the entire PDF is generated, all pages will be blank except for the first 2.

images/duproductspdf.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 Usecases

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 2 - Products by Supplier in the outline. Activate the view and click on the button Create Productlist. 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 Productlist and modify them where necessary.
  • Check all filepaths used in the products.cmd and modify them where necessary.

The agent ProductList

You can find the agent ProductList 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 suppliers and products is traversed and the XML-structure is built. Then XMLMill-batch is called to transform the XML-file combined with the according XSLT-file into a PDF. The agent then checks wether the PDF-file is ready and attaches the PDF to a 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. Embedding and linking the generated PDF in a Notes-document.

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 supplier As String
[009] 	Dim family As String 
[010] 	Dim filename As String
[011] 	Dim filenum As Integer
[012] 	Dim taskId As Integer
[013] 	Dim pathName As String
[014] 	Dim pdfdoc As notesdocument
[015] 	Dim rtitem As NotesRichTextItem
[016] 	Dim object As NotesEmbeddedObject	
[017] 	Dim pdfview As notesview
[018] 	supplier=""
[019] 	family=""
[020] 	filenum=1
[021] 	filename= "\\lab_server\xmlmill\domino\products.xml"
[022] 	

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\products.xml". This file can be placed somewhere on your filesystem. Make sure however that the user running the agent is able to write to the specified directory on your filesystem. We assign the variables supplier and family blank values. These variables will be used once we start looping through the view.

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("(LUSupFam)")
[006] Set doc=view.getfirstdocument

The view we will loop through in order to build the xml-structure is (LUSupFam). It contains all products, sorted by supplier and productfamily.

Start creating the XML-structure

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

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=""productsshort.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 <productdata>.

Traversing through documents in the view

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

[001] 	<productdata>
[002] 	<supplier> <name> Supplier1 </name>
[003] 		<family> <type> Family A </type>
[004] 			<product>
[005] 				<code> 11111 </code>
[006] 				<description> AAAA </description>
[007] 				<price> 10 </price>
[008] 				<weight> 20 </weight>
[009] 				<date> 31-12-2010 </date>
[010] 			</product>
[011] 			<product>
[012] 				<code> 22222 </code>
[013] 				<description> BBBB </description>
[014] 				<price> 10 </price>
[015] 				<weight> 20 </weight>
[016] 				<date> 31-12-2010 </date>
[017] 			</product>
[018] 		</family>
[019] 		<family> <type> Family B </type>
[020] 		.....
[021] 		</family>
[022] 	</supplier>
[023] 	<supplier> <name> Supplier 2 </name>
[024] 	.......
[025] 	</supplier
[026] </productdata>
  • Every supplier has 1 name and supplies 1 or more productfamilies.
  • Every productfamily has 1 name and contains 1 or more products.
  • Every product has exactly 1 serialnumber, description, weight, price and expiration date.

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] 	If supplier <> doc.productsupplier(0) Then
[006] 
[007] 		If supplier <>"" Then
[008] 
[009] 			Print #filenum,"</family>"
[010] 			Print #filenum,"</supplier>"
[011] 		
[012] 		End If
[013] 
[014] 		Print #filenum,"<supplier>  <name> "+  doc.productsupplier(0)+ " 
        </name>"
[016] 		Print #filenum,"<family> <type> " + doc.productfamily(0)+ " </type>"
[017] 			
[018] 			
[019] 	Elseif family <> doc.productfamily(0)  Then
[020] 		Print #filenum,"</family>"
[021] 		Print #filenum,"<family> <type> " + doc.productfamily(0)+ " </type>"
[022] 	End If
[023] 	
[024] 	Print #filenum,"<product>"
[025] 	Print #filenum,"<code>" + doc.productserialnr(0)+ "</code>"
[026] 	Print #filenum,"<description>" + doc.productdescription(0) + 
       "</description>"
[028] 	Print #filenum,"<price>" + Cstr(doc.productprice(0)) + "</price>"
[029] 	Print #filenum,"<weight>" + Cstr(doc.productweight(0)) + "</weight>"
[030] 	Print #filenum,"<date>" + Cstr(doc.productdate(0))+ "</date>"
[031] 	Print #filenum,"</product>"
[032] 	
[033] 	supplier=doc.productsupplier(0)
[034] 	family=doc.productfamily(0)
[035] 
[036] 	Set doc=view.getnextdocument(doc)
[037] Wend
[038] 	

When we start reading the first document in the view, the variables supplier and family are blank, since we initialized these as blank strings at the beginning of the agent. For the first document the value of the document supplier is different from blank, so we know this is a new supplier and we will have to write the opening element: <supplier>. Because the last known value is blank and not some other value, we know this is the first document and we don't have to close a preceding tag.

Since a supplier has a name, we open the tag <name>, fill it with the supplier name in the first document and close the tag again:

[001] Print #filenum,"<supplier>  <name> "+  doc.productsupplier(0)+ " 
      </name>"

Since we have encountered a new supplier, we have to open a new productfamily too. The productfamily element consists of 2 children: <type> and <product>. Every productfamily has one type and consists of one or more products. We fill the type element with the value of the productfamily of the first document and close the tag again:

[001] Print #filenum,"<family> <type> " + doc.productfamily(0)+ " 
      </type>"

Every productfamily consists of 1 or more products. A product has different characteristics: <code>, <description>,<price>,<weight> and <date>. So, for the first document, we have to open a new <product> element, followed by the different tags for the product characteristics:

[001] 
[002] Print #filenum,"<product>"
[003] 	Print #filenum,"<code>" + doc.productserialnr(0)+ "</code>"
[004] 	Print #filenum,"<description>" + doc.productdescription(0) + 
       "</description>"
[006] 	Print #filenum,"<price>" + Cstr(doc.productprice(0)) + "</price>"
[007] 	Print #filenum,"<weight>" + Cstr(doc.productweight(0)) + "</weight>"
[008] 	Print #filenum,"<date>" + Cstr(doc.productdate(0))+ "</date>"
[009] Print #filenum,"</product>"

Before moving to the next document, we assign the variables supplier and family the values found in the first document:

[001] 
[002] supplier=doc.productsupplier(0)
[003] family=doc.productfamily(0)
[004] 
[005] Set doc=view.getnextdocument(doc)
[006] Wend

When we move to the next document, 3 situations can occur:

  1. The next document represents a new supplier.
  2. The next document represents the same supplier, but a new productfamily.
  3. The next document represents the same supplier and productfamily.

The next document represents a new supplier

The value of the supplier of the next document differs from the last known value of the variable supplier. We know we have a new supplier, so we must open new supplier-, family- and product elements. Since the last known value of supplier is not blank, we know this is not the first document and we have to close the preceding family and supplier elements:

[001] 
[002] If supplier <> doc.productsupplier(0) Then
[003] 	If supplier <>"" Then
[004] 
[005] 			Print #filenum,"</family>"
[006] 			Print #filenum,"</supplier>" 
[007] 	
[008] 	End If
[009] 		
[010] 		Print #filenum,"<supplier>  <name> "+  doc.productsupplier(0)+ " 
        </name>"
[012] 		Print #filenum,"<family> <type> " + doc.productfamily(0)+ " </type>"

Then we have to reopen/close the product tags the same way as for the first document and fill them with the values of the second document:

[001] Print #filenum,"<product>"
[002] 	Print #filenum,"<code>" + doc.productserialnr(0)+ "</code>"
[003] 	Print #filenum,"<description>" + doc.productdescription(0) + 
       "</description>"
[005] 	Print #filenum,"<price>" + Cstr(doc.productprice(0)) + "</price>"
[006] 	Print #filenum,"<weight>" + Cstr(doc.productweight(0)) + "</weight>"
[007] 	Print #filenum,"<date>" + Cstr(doc.productdate(0))+ "</date>"
[008] Print #filenum,"</product>"

Before moving to the next document, we assign the variables supplier and family the values found in the current document. We repeat the preceding steps until the view is completely processed.

The next document represents the same supplier but a new productfamily

The value of the supplier of the next document is the same as the last known value of the variable supplier, but the value of the family differs from the last known value of the variable family. So we know we have the same supplier, but a different family and we must open new productfamily en product elements. Since the value of supplier is not blank, we know this is not the first document and we have to close the preceding family element.

[001] 
[002] Elseif family <> doc.productfamily(0)  Then
[003] 		Print #filenum,"</family>"
[004] 		Print #filenum,"<family> <type> " + doc.productfamily(0)+ " </type>"
[005] End If

Then we have to reopen/close the product tags the same way as for the first document and fill them with the values of the second document:

[001] Print #filenum,"<product>"
[002] 	Print #filenum,"<code>" + doc.productserialnr(0)+ "</code>"
[003] 	Print #filenum,"<description>" + doc.productdescription(0) + 
       "</description>"
[005] 	Print #filenum,"<price>" + Cstr(doc.productprice(0)) + "</price>"
[006] 	Print #filenum,"<weight>" + Cstr(doc.productweight(0)) + "</weight>"
[007] 	Print #filenum,"<date>" + Cstr(doc.productdate(0))+ "</date>"
[008] Print #filenum,"</product>"

Before moving to the next document, we assign the variables supplier and family the values found in the current document. We repeat the preceding steps until the view is completely processed.

The next document represents the same supplier and productfamily

The next document belongs to the same productfamily and supplier, so we do not have to close any supplier or family element. Al we have to do is open the product elements and fill them with the values of the second document.

[001] Print #filenum,"<product>"
[002] 	Print #filenum,"<code>" + doc.productserialnr(0)+ "</code>"
[003] 	Print #filenum,"<description>" + doc.productdescription(0) + 
       "</description>"
[005] 	Print #filenum,"<price>" + Cstr(doc.productprice(0)) + "</price>"
[006] 	Print #filenum,"<weight>" + Cstr(doc.productweight(0)) + "</weight>"
[007] 	Print #filenum,"<date>" + Cstr(doc.productdate(0))+ "</date>"
[008] Print #filenum,"</product>"

Before moving to the next document, we assign the variables supplier and family the values found in the current document. We repeat the preceding steps until the view is completely processed.

Xml ending tags

[001] 
[002] '5) xml ending tags
[003] 
[004] Print #filenum,"</family>"
[005] Print #filenum,"</supplier>"
[006] Print #filenum,"</productdata>"
[007] Close fileNum
[008] 	

When the last document has been processed, the remaining opened tags are closed by adding: </family>, </supplier> and </productdata>. The file is closed and ready to be processed by XMLMill.

Start preparing for XMLMill-batch

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

After generating the PDF, we want the agent to capture the PDF-file and attach it to a Notes-document. Therefore we need a means to know when the PDF-file is ready. This is why we introduce a small text-file ended.txt. When this file is present, this means the PDF is 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\products.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 PDF, 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 products.cmd in the next sections.

Embedding and linking the generated PDF in a Notes-document

[001] '7) Embedding and linking PDF in Notes-document
[002] 	
[003] Set pdfview=db.getview("(LUPDFContainer)")
[004] Set pdfdoc=pdfview.getfirstdocument
[005] 
[006] If pdfdoc Is Nothing Then
[007] 
[008]  Set pdfdoc=db.CreateDocument
[009]  pdfdoc.form="PDFContainer"
[010]  Set rtitem = pdfdoc.CreateRichTextItem("PDFAttachment" )
[011]  Set object = rtitem.EmbedObject(EMBED_ATTACHMENT,"",
[012]  "\\lab_server\xmlmill\domino\output\products.pdf")
[013]  pdfdoc.pdflink="file:\\lab_server\xmlmill\domino\output\products.pdf" )
[014] 
[015] Else
[016] 
[017]  Set rtitem = pdfdoc.GetFirstItem("PDFAttachment" )
[018]  
[019]  If ( rtitem.Type = RICHTEXT ) and doc.hasembedded Then
[020] 	Forall o In rtitem.EmbeddedObjects
[021] 		Call  o.remove
[022] 	End Forall
[023]  
[024]  Set object = rtitem.EmbedObject(EMBED_ATTACHMENT,"",
[025]  "\\lab_server\xmlmill\domino\output\products.pdf")
[026]  
[027]  End If
[028] 
[029] End If
[030] 
[031] Call pdfdoc.save(True,False)
[032] 
[033] End 
      Sub	

After the generation of the PDF, we want to attach it to a Notes-document. As an alternative we also show you how to create a link to the PDF-file in case you do not want to attach the file. After the PDF is attached and the link is provided, the Notes-document will look like this:

images/duproductspdfcontainer.jpg
Select to enlarge

So, first we define the view containing the document with the PDF-document (PDFContainer). We check if such a document already exists.

  • If the containerdocument doesn't exist already (the first time it is generated), we create a new document, and embed the PDF as an attachment to a new richtext-item PDFAttachment. Next, 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.
  • If the containerdocument already exists, we check if there are attachments present in the field PDFAttachment. If there are, we remove them. Next we embed the newly generated PDF as an attachment to the field PDFAttachment. Note that we do not have to change the link, because it is just a pointer to the file and the location and name of the PDF are always the same.

The XSLT-stylesheet productsshort.xsl

Overview

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

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

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

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

[001] ...
[002] <xsl:template match="/">
[003]   <ml:documents  whitespace-collapse="on" space-collapse="on">
[004]   ... 

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

As a result the <mldocuments> element is processed. The <documents> element is the root tag of the ml: namespace. It can contain multiple <ml:document> elements each contaning elements to define a separate pdf document.

The <ml:document> element

[001] <ml:document file="output\quotes.pdf" 
      >

The <document> element contains the file attribute defining the name and path (optional) of the .pdf document to generate.

The <ml:navigation> element

[001] <navigation number-format="1.1" outlines="on" table-of-contents="on"/> 

The <navigation> element defines that the document generated should contain a table of contents and an outlines (bookmarks). The number-format for the toc and the outline in the example is set to 1.1. Other possibilities of number format are eg. 1.A., A.I.,...

The <ml:layout-master-set> element

For your convenience please find below the structure of the <ml:layout-master-set> content.

[001] ...
[002]   <ml:layout-master-set>  
[003]         <!-- Define a separate page-sequence for the table-of-contents.  
              -->
[005]           <ml:simple-page-master master-name="toc">
[006]             <ml:region-body />
[007]             <ml:region-before />
[008]             <ml:region-after />
[009]           </ml:simple-page-master> 
[010]         
[011]        <!-- Define a page-sequence for the content pages  -->              
                
[013]           <ml:simple-page-master master-name="content-pages">
[014]             <ml:region-body />
[015]             <ml:region-before />
[016]             <ml:region-after />
[017]           </ml:simple-page-master> 
[018]   </ml:layout-master-set>
[019] ...

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>).

In this example 2 simple page masters are defined: a simple page master for the page(s) where the table-of-contents will be displayed and a simple page master for the other pages.

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.

The <ml:page-sequence> element

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).

This example contains two <page-sequence>s:

  • A page-sequence for the table of content pages.
  • A page-sequence for the other pages.

Page-sequence for the table of content pages

[001] 
[002] <ml:page-sequence initial-page-number="1" master-reference="toc">
[003]   <!-- The static content (the header and footer). -->
[004]   <ml:static-content flow-name="xsl-region-before">
[005]     ...
[006]   </ml:static-content>
[007]   <ml:static-content flow-name="xsl-region-after">
[008]     ... 
[009]   </ml:static-content>
[010]   <ml:flow flow-name="xsl-region-body">
[011]     <!-- Define the layout of the table-of-contents -->          
[012]     <ml:table-of-contents right-align-page-number="on" ... >
[013]       <!-- Define the table of contents header (caption) -->
[014]       <ml:toc-header ... >Table of Contents</ml:toc-header>
[015]       <!-- Define the format for each level in the table of contents. -->
[016]       <ml:toc-style level="1" .../>
[017]       <ml:toc-style level="2" .../>
[018]       <ml:toc-style level="3" .../>
[019]       <ml:toc-style level="4" .../>
[020]     </ml:table-of-contents>
[021]   </ml:flow>
[022] </ml:page-sequence>
[023]           

The <flow> element contains also the <ml:table-of-contents> element and its children which define the characteristics of the table of content.

  • For more information regarding these elements please visit the dtdguide.pdf document contained in the docs/ directory in the download.(

Page-sequence for the content pages

[001] 
[002] <ml:page-sequence initial-page-number="1" 
      master-reference="content-pages">
[004]   <ml:static-content flow-name="xsl-region-before">
[005]     ...
[006]   </ml:static-content>
[007]   <ml:static-content flow-name="xsl-region-after">
[008]     ...
[009]   </ml:static-content>
[010]   <ml:flow flow-name="xsl-region-body">
[011]     ...
[012]   </ml:flow>
[013] </ml:page-sequence>   
[014]             

The second page-sequence is used to format and describe the content of the other pages of the document.

  • 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 products.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] 
[018] 
[019] @echo on
[020] 
[021] REM %JAVA_HOME% com.xmlmill.batch.Main -?
[022] 
[023] %JAVA_HOME% com.xmlmill.batch.Main  -m 
      \\lab_server\xmlmill\domino\products.xml -s 
      \\lab_server\xmlmill\domino\productsshort.xsl -l Products.log -v
[026] 
[027] copy \\lab_server\xmlmill\domino\output\starting.txt 
      \\lab_server\xmlmill\domino\output\ended.txt 

As a special add-on for this use case, we copy a little file "starting.txt" to "ended.txt", so that our agent knows when the PDF-file is ready. You can find the text-file in the domino\output-directory in the download. Make sure that you modify the copy-instruction in the products.cmd file, so that it points to the right directory for your environment.

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\products.xml -s 
      \\lab_server\xmlmill\domino\productsshort.xsl -l Products.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.

  • More information regarding XMLMill in batch can be found in the userguide.pdf document contained in the docs/ directory in the download.
Copyright © 2001 - 2012. All rights reserved. XMLMill and XMLMill logo are trademarks of Pecunia Data Systems, bvba.
Powered by Apache CocoonPowered by XMLMill