ODTCreatorUnit
Class name |
com.ebd.hub.datawizard.iu.ODTCreatorUnit |
This Integration Unit can be used to create text documents in Open Document format. This is supported by a number of office packages and text processors, among others OpenOffice 2.0.
The office document will be created on the basis of a template file, which can simply be created in OpenOffice as a text document, for example. This document has to be stored as a regular text document and not as a template within OpenOffice.
Parameters
Parameter name |
Allowed values |
Default value |
Description |
create multiple files |
true, false |
false |
To create multiple documents instead of a single one. |
directory |
|
|
The output directory. |
file pattern |
|
|
File name pattern for the generated documents, if the integration unit saves them (if save files is set to true). The pattern can contain placeholders. Allowed placeholders are y, M, d, h, m, s, S and n. |
keep linebreaks within text |
true, false |
false |
If true, line breaks of values are taken over into the template, otherwise they are displayed as spaces. |
root node for multiple files |
|
|
Every instance of this node will create a single document if create multiple files is set to true. All nodes of the target structure above this node are not reachable. The template always has to have an outmost block corresponding to the root node. |
save files |
true, false |
false |
If true, the integration unit itself will save the file(s) (mandatory). |
template-file |
|
|
The text document serving as a template. |
unknown tags replacement |
|
? |
Unknown tags will be replaced with this character sequence. |
Example for parameter "file pattern"
For invoice<yyyy><MM><dd>_<HH><mm>
a profile run at 24.02.2006, 12:30 pm would create a file with name:
invoice20060224_1230.odt
Or, if parameter create multiple files is set to true, multiple files with names:
invoice20060224_1230_Part1.odt
invoice20060224_1230_Part2.odt
invoice20060224_1230_Part3.odt
...
Format of the template
Templates are normal text files in Open Document Format (ODF). The usual ending for such a file is .odt. In the following, we assume that this file was created with OpenOffice 2.0. Certain placeholders (tags, blocks, and commands) can be used in the text, headers, and footers of the template to describe how the ODTCreatorUnit has to create the document. These placeholders are either replaced by the content of a field or they limit blocks, which are repeated for each occurrence of a corresponding node. In addition, there are special commands for additional control.
Tags:
All tags are opened with {-- and closed with --}:
{--Tag--}
Whitespaces between the field names, block names, commands and the enclosing brackets are not allowed.
{--Correct--}
{-- Incorrect --}
If a tag is unknown (e.g. because the used field does not exist), the default output instead of the field value is a ?. The unit parameter unknown tags replacement allows defining alternative characters.
Blocks:
Blocks are, similar to XML, closed with a slash /. All tags enclosing blocks always have to stand at the beginning of a line only containing that tag. Those lines are removed after the processing of the template.
This {--Block--} is totally
wrong. {--/Block--}
{--Block--}
This is correct.
{--/Block--}
Blocks have to correspond to nodes in the data structure. The content of a block is repeated as often as the respective node (once per data set of that node).
A node or a field can always just be addressed in a block referring to a directly superordinate node. In the following example the node ItemHead can only be addressed in the block Item, but not in the block Invoice. If a block is unknown (e.g. because the corresponding node does not exist), the whole node will not be displayed.
The outmost block of a template always has to correspond to the node set as root node (if the option create multiple files is used). This does not have to be the outmost node. On the other hand, if root node and create multiple files are not used, the outmost block indeed has to correspond to the outmost node of the destination tree. If there are several nodes on the highest level, all of them can be addressed.
Commands:
Commands always begin with odtcreator, followed by a colon and the command itself. After that, optional parameters, separated by colons, can follow. Commands can also form blocks. In this case, the closing tag /odtcreator:<command> is sufficient and additional statements are ignored.
For example:
{--odtcreator:if:equal:Salutation:Mr--}
Content of the block
{--/odtcreator:if:this is ignored:this as well:this too--}
Following a practical example for a better understanding. The data of several invoices shall be converted into separate invoice documents.
Exemplary data structure and data
Exemplary data structure
As you can see, every invoice has an invoice header, the recipient's address and one or several items. Every item again has a header and may contain several data sets of detail or additional information. In the node Sums the sum of all item totals is calculated.
|
|
|
|
Whole structure, top level. |
Expanded nodes Header and Address. |
Expanded nodes ItemHeader, ItemDetail and ItemAddition. |
Expanded node Sums. |
Exemplary data
RK;R2006-100;C0815;20.02.2006;A2006-98;23.02.2006;L2006-98
AD;Miller;Peter;10 Main Street;CM19 6EA;Anytown;Mr
RP;1;4711;1;"Hard Disc Drive Turbo 300";149.99;149.99
PD;"Internal Hard Disc Drive Turbo 300, EIDE, 300 GB"
RP;2;4712;1;"DVD Burner";89.99;89.99
PD;"External DVD Burner, USB2"
RP;3;4713;5;"Blank DVD Discs";2.99;14.95
PD;"Blank DVD-RW Discs"
RP;4;4714;2;"Toner";129.99;259.89
PD;"Toner Cartridge for Laser Printer"
PD;"Suitable for HP Laserjet"
RK;R2006-101;C0300;21.02.2006;A2006-102;23.02.2006;L2006-102
AD;Brown;Mary;77 Royal Terrace;CM18 6EB;Greattown;Mrs
RP;1;8810;1;"All-in-One System";499.99;499.99
PD;"All-in-One Desktop PC"
PD;"Processor: Athlon 3,2 GHz"
PD;"1 GB RAM"
PZ;"Special offer"
RP;2;8820;1;"USB Flash Drive";49.98;49.98
PD;"USB Flash Drive, 1 GB, USB2"
RP;3;8830;1;"SUSE";39.95;39.95
PD;"SUSE Linux Professional"
PD;"Version 10.0"
Example templates
A first template
As you can see in the exemplary data, two invoices should be generated. One for Mr Peter Miller and one for Mrs Mary Brown. To achieve that, we set the parameters create multiple files to true and root node for multiple files to Invoice. For starters, we only display the header information and the address. Our template is an .odt file with the following content:
This already shows us the most important elements of such a template: Blocks and field placeholders.
Everything in between the elements {--Invoice--} and {--/Invoice--}, for example, is a block. This means that all the fields and further blocks between those two tags correspond to the node Invoice. If create multiple files were set to false, only one document, containing the header information and address of every invoice, would be created.
Two further blocks are opened in the block Invoice. One for the header information and one for the address. The tags for those blocks are named exactly like the nodes containing the corresponding fields: Header and Address. All the field placeholders within those blocks are replaced with the values of the corresponding fields, i.e. fields with the exact same name. So {--OrderNumber--} or {--Title--} for example. The lines with Postcode and City show that any desired formatting is possible. The values replacing the placeholders will have the same formatting.
So far, our invoice for Mr Miller looks like this:
Template_2_EN.odt (This is not a template. It is a result of a processed template.)
An extended template
Now we need a salutation, which will be straightforward:
Next, we want to list all the items of the invoice. This shall be done in a table. First, we show the simple version:
The Integration Unit repeats the content of the table (the header row is not repeated) for each Item and fills the placeholders with the field values of the respective subnode ItemHeader. As you can see, blocks can be put in table cells as well, but opening and closing tags also have to be in lines only containing those tags. However, that is not very readable. So why do we not refer the table directly to the node ItemHeader? Unfortunately, that is not possible, since a node can always just be addressed in a block referring to a directly superordinate node, as mentioned earlier, and the superordinate node of IteamHeader is Item and not Invoice.
But we have a solution for that. Instead of the command table we use table deep:
This version searches deep down in the subnodes of Invoice for occurrences of the node ItemHeader and repeats the table contents for those nodes.
Now all that is missing is the total sum over all items:
List of all commands
Following a list of all commands that can be used to control the ODTCreatorUnit. If a command encloses a block, we call it a block tag. If it is replaced by a value, we call it a value tag. Additionally, there are action tags that have a control function and do not directly influence the creation of the document.
table
Type: Block tag
Format: odtcreator:table:<node name>
A table block always encloses a table. The content rows of the table are repeated for each dataset with the specified node while the header line will only be displayed once. The header line is usually generated automatically when the table is created (in OpenOffice). If the table shall contain several header lines that are repeated for each data set, you are not allowed to use 'real' header lines. Delete the 'real' header line and replace it with a normal line that is simply formatted as if it were a header line.
The node used for the table has to be directly underneath the node of the current block. Inside the table block, you are in the referred block and have access to its fields and nodes.
tabledeep
Type: Block tag
Format: odtcreator:tabledeep:<node name>
The tabledeep command basically works like the table command, but the node used for the table does not have to be directly underneath the node of the current block. Under certain circumstances, that can save a few blocks if they are only needed to reach the node used for the table.
deep
Type: Block tag
Format: odtcreator:deep:<node name>
Similar to tabledeep, you can save a few blocks if you only need quick access to a node several levels below the current node. In our invoice example, we could go directly from block Invoice to block ItemHeader. Using 'normal' blocks, you would have to go to the node Item first.
Example without deep:
{--Invoice--}
...
{--Item--}
{--ItemHeader--}
Position {--PositionNumber--}: Item number {--ItemNumber--}, {--ShortDescription--}
{--/ItemHeader--}
{--/Item--}
...
{--/Invoice--}
Example with deep (in just one step):
{--Invoice--}
...
{--odtcreator:deep:ItemHeader--}
Position {--PositionNumber--}: Item number {--ItemNumber--}, {--ShortDescription--}
{--/odtcreator:deep--}
...
{--/Invoice--}
parent
Type: Block tag
Format: odtcreator:parent
This command can be used to go up one hierarchy level. The content in the parent block then refers to the data set of the superordinate node. If you used another parent block inside the block, you could go even higher.
Example:
{--Invoice--}
...
{--odtcreator:deep:ItemHeader--}
Position {--PositionNumber--}: Item number {--ItemNumber--}, {--ShortDescription--}
{--odtcreator:parent--}
Detail information:
{--ItemDetail--}
{--DetailText--}
{--/ItemDetail--}
Additions:
{--ItemAddition--}
{--AdditionalText--}
{--/ItemAddition--}
{--/odtcreator:parent--}
{--/odtcreator:deep--}
...
{--/Invoice--}
if
Type: Block tag
Format: odtcreator:if:equal:<field>:<value>
or: odtcreator:if:notequal:<field>:<value>
or: odtcreator:if:textis:<value>
or: odtcreator:if:textisnot:<value>
or: odtcreator:if:inelement:<element name>
Conditions equal and notequal:
This block will only be evaluated if the stated field has the desired value (equal), or not (notequal).
Conditions textis and textisnot:
If you are in a block that refers to a field, you can check the value of that field.
Condition inelement:
This condition only makes sense in an in block. The if block is only evaluated if you currently are in an element (node or field) with the specified name. An example can be found in the description of the in command (example 2).
Example 1: equal
{--Invoice--}
...
{--Address--}
...
{--odtcreator:if:equal:Title:Mr--}
Our special offer for the gentlemen: ShaveTech USB travel razor for 9.99. Check out our website.
{--/odtcreator:if--}
{--odtcreator:if:equal:Title:Mrs--}
Our special offer for the ladies: USB Hand Warmer Mouse Pad for 8.99. Check out our website.
{--/odtcreator:if--}
{--/Address--}
...
{--/Invoice--}
The condition notequal is evaluated accordingly.
Example 2: textis
{--Invoice--}
...
You get a special offer price for following item:
{--odtcreator:deep:AdditionalText--}
{--odtcreator:if:textis:Special offer--}
{--odtcreator:parent--}
{--odtcreator:parent--}
{--ItemHeader--}
Position {--PositionNumber--}: Item number {--ItemNumber--}, {--ShortDescription--}
{--/ItemHeader--}
{--/odtcreator:parent--}
{--/odtcreator:parent--}
{--/odtcreator:if--}
{--/odtcreator:deep--}
...
{--/Invoice--}
In this example, all the additional texts are checked for containing the value Special offer. If so, the header information of the respective item is displayed. For this purpose, we have to work our way up, starting at AdditionalText via ItemAddition (1. parent) to Item (2. parent) and then step into the node ItemHeader. The condition textisnot is evaluated accordingly.
in
Type: Block tag
Format: odtcreator:in:[list of node names] or odtcreator:in:*
This command allows you to access all the subordinate nodes and fields of the current node. You either specify the desired node names (separated by :) or use an asterisk (*) for all subordinate nodes.
Example 1: Display the names and values of all fields of node ItemHeader
{--Invoice--}
...
{--odtcreator:deep:ItemHeader--}
Position {--PositionNumber--} has the following content:
{--odtcreator:in:*--}
{--odtcreator:elementname--} = {--odtcreator:elementtext--}
{--/odtcreator:in--}
{--/odtcreator:deep--}
...
{--/Invoice--}
The commands elementname and elementtext are explained below.
Example 2: Combined with if:inelement
{--Invoice--}
...
{--Item--}
{--odtcreator:in:ItemHeader:ItemAddition--}
{--odtcreator:if:inelement:Item Header--}
Position {--PositionNumber--}: Item number {--ItemNumber--}, {--ShortDescription--}
{--/odtcreator:if--}
{--odtcreator:if:inelement:ItemAddition--}
Addition: {--AdditionalText--}
{--/odtcreator:if--}
{--/odtcreator:in--}
{--/Item--}
...
{--/Invoice--}
In the block referring to the node Item, the in command passes through the nodes ItemHeader and ItemAddition. Depending on which subordinate node is currently accessed, the corresponding row is displayed. Of course, this is a bit useless in this case, since we could have accessed the nodes directly, but it shows the principle.
elementname and elementtext
Type: Value tag
Format: odtcreator:elementname or odtcreator:elementtext
Those two tags are replaced with the name of the current element (node or field), respectively the text (the value) if it is a field. An example can be found in the description for command in (example 1).
define and undefine
Type: Action tag
Format: odtcreator:define:<arbitrary text> or odtcreator:undefine:<arbitrary text>
Those two tags have no direct effect on the text and are replaced with an empty string. However, the ODTCreatorUnit remembers the specified text as defined, respectively deletes that definition again. Such a definition can be used for checks in the commands ifdef and ifundef (see below).
In the following example, we extend the display of the special offer items (example 2 of the if command) by one row that is only displayed if no special offer item has been found. For this purpose, we use the command ifundef.
Example: Display line, if there are no special offers
{--Invoice--}
...
You get a special offer for following items:
{--odtcreator:deep:AdditionalText--}
{--odtcreator:if:textis:Special offer--}
{--odtcreator:parent--}
{--odtcreator:parent--}
{--ItemHeader--}
Position {--PositionNumber--}: Item number {--ItemNumber--}, {--ShortDescription--}
{--odtcreator:define:Special offer found--}
{--/ItemHeader--}
{--/odtcreator:parent--}
{--/odtcreator:parent--}
{--/odtcreator:if--}
{--/odtcreator:deep--}
{--odtcreator:ifundef:Special offer found--}
Unfortunately there are no special offers for your order.
{--/odtcreator:ifundef--}
...
{--/Invoice--}
If you want to do a similar check later, you can delete the definition {–odtcreator:undefine:Special offer found–}.
ifdef and ifundef
Type: Block tag
Format: odtcreator:ifdef:<arbitrary text> or odtcreator:ifundef:<arbitrary text>
The ifdef block is only evaluated if the specified text has been defined with the define command. The ifundef block, on the other hand, is evaluated if the specified text has not been defined, or has been erased by the undefine command. An example for the usage of ifundef can be found in the description of the commands define and undefine (ifdef is used accordingly).