PDF Generation
iXML provides a complete PDF generation engine through the pdf namespace. You can create multi-page documents with headers, footers, styled text, tables, images, barcodes, and imported templates -- all from XML markup.
Document Structure
Every PDF follows a strict hierarchy:
pdf:document <- document root (produces binary output)
├── pdf:file <- embedded file attachment (PDF/A)
└── pdf:section <- page layout definition (one or more)
├── pdf:templates <- background template pages
│ └── pdf:template <- individual template page mapping
├── pdf:header <- repeated header content
├── pdf:footer <- repeated footer content
└── pdf:body <- main page content
├── pdf:style <- typography and layout styling
├── pdf:block <- block-level text
├── pdf:inline <- inline flow text
├── pdf:row <- table row
│ └── pdf:col <- table column
├── pdf:image <- image
├── pdf:barcode <- barcode (1D or 2D)
├── pdf:linebreak <- vertical spacing
├── pdf:pagebreak <- force new page
├── pdf:include <- insert external PDF pages
├── pdf:getpos <- read current position
└── pdf:setpos <- set current position
Content elements can appear inside pdf:header, pdf:footer, or pdf:body.
Document Root
pdf:document
Creates a PDF document. All sections and content are defined as children. The resulting binary is stored in the variable specified by var. Supports metadata attributes (title, author, subject, keywords), pdfa for PDF/A-3 compliance, compress and subsetting for size optimization, and unit for measurement (default mm).
pdf:signature
Adds a digital signature to the PDF document using PEM-encoded certificates and private keys. Child of pdf:document (single occurrence).
Full reference ->
pdf:file
Embeds a file attachment in the PDF document. Primarily used with PDF/A-3 for structured data embedding (e.g., ZUGFeRD e-invoicing XML).
Page Layout
pdf:section
Defines a page section with its own orientation, format, margins, header, footer, and body. A document can contain multiple sections with different page setups. Common formats: A4, A3, A5, LETTER, LEGAL.
pdf:templates
Defines a set of template pages to overlay as a background, loaded from an external PDF via filename. Contains pdf:template children mapping source pages to target pages. Commonly used for letterheads and branded backgrounds.
pdf:template
Maps a page from the template PDF to a target page in the generated document. Child of pdf:templates. Use source for the template page number and target for the output page number (omit target to apply to all pages).
Typography and Styling
pdf:style
Defines visual styling for child content. Styles cascade -- each child inherits from its parent and overrides specific properties. Controls alignment, font (font, fontsize, fontstyle), colors (textcolor, bgcolor), borders (border, borderwidth, bordercolor), lineheight, padding, and rotate.
Font style characters can be combined: B (bold), I (italic), U (underline), O (overline), D (line-through). For example, fontstyle="BIU" produces bold italic underlined text.
Border sides are specified as a string of characters: "TBLR" draws all four borders, "TB" draws top and bottom only.
Text Content
pdf:block
Prints a block of text. Each block starts on a new line and occupies the full available width. Supports html mode for basic HTML tags (<b>, <i>, <u>, <br>), absolute positioning via x/y, and explicit width/height.
When using html="t", HTML tags must be XML-escaped (e.g., <b> for <b>) because the content is parsed as XML first.
pdf:inline
Prints text as inline flow content. Unlike pdf:block, inline text does not start a new line -- multiple inline elements flow on the same line.
Table Layout
pdf:row
Defines a row of columns for tabular content. Row height adjusts to the tallest column. Contains one or more pdf:col children.
pdf:col
Defines a column within a pdf:row. Each column has its own width, and supports html, nowrap, and height.
Always set explicit width on every pdf:col. Without widths, columns expand to the right margin, making multi-column layouts unpredictable.
Media Content
pdf:image
Inserts an image from a file path or URL. Supports width, height, dpi, and absolute positioning via x/y. When only one dimension is specified, the image scales proportionally.
pdf:barcode
Prints a 1D or 2D barcode. Supports QR codes (QRCODE, QRCODE,M, etc.), Code 128 (C128), EAN (EAN8, EAN13), DataMatrix, PDF417, and many more. The element content is the data to encode.
Page Flow Control
pdf:linebreak
Adds vertical spacing by the given offset (in document units).
pdf:pagebreak
Forces a new page. Optionally shifts the ordinate to a given offset on the new page.
pdf:pagebreak behaves like pdf:linebreak when used inside pdf:header or pdf:footer. It only creates a new page when used inside pdf:body.
pdf:include
Imports and inserts pages from an external PDF document. Use from and to to select a page range. Useful for appending terms and conditions or pre-designed content.
pdf:include inserts pages as full content pages, while pdf:templates overlays a template as a background behind your generated content. pdf:include has no effect inside pdf:header or pdf:footer.
Position Control
pdf:getpos
Reads the current drawing position. Stores the page number (var_page, var_subpage) and coordinates (var_x, var_y) into variables. Essential for dynamic layout control and page numbering in headers/footers.
pdf:setpos
Sets the current drawing position explicitly via page, x, and y. Enables absolute positioning and overlay effects.
Practical Patterns
Minimal Document
<pdf:document var="pdf" title="Hello World">
<pdf:section>
<pdf:body>
<pdf:block>Hello, PDF!</pdf:block>
</pdf:body>
</pdf:section>
</pdf:document>
<size var="len">$pdf</size>
<output>PDF size: $len bytes</output>
Serving a PDF as HTTP Response
<pdf:document var="pdf" title="Invoice #1234" author="ZeyOS">
<pdf:section format="A4">
<pdf:body>
<pdf:block>Invoice content here</pdf:block>
</pdf:body>
</pdf:section>
</pdf:document>
<header>Content-Type: application/pdf</header>
<header>Content-Disposition: attachment; filename="invoice-1234.pdf"</header>
<output>$pdf</output>
Use Content-Disposition: inline to display the PDF in the browser instead of triggering a download.
Invoice with Line Items
This example demonstrates a realistic invoice layout combining most PDF commands:
<pdf:document var="pdf" title="Invoice" author="ZeyOS" compress="t" subsetting="t">
<pdf:section format="A4" orientation="P"
leftmargin="20" rightmargin="20" topmargin="25" bottommargin="20">
<pdf:header>
<pdf:style fontsize="8" textcolor="#999999" align="R">
<pdf:getpos var_page="p"/>
<pdf:block>Page $p</pdf:block>
</pdf:style>
</pdf:header>
<pdf:body>
<!-- Title -->
<pdf:style fontsize="18" fontstyle="B">
<pdf:block>INVOICE</pdf:block>
</pdf:style>
<pdf:linebreak offset="10"/>
<!-- Customer info -->
<pdf:style fontsize="10">
<pdf:block>Customer: Ada Lovelace</pdf:block>
<pdf:block>Date: 2024-01-15</pdf:block>
</pdf:style>
<pdf:linebreak offset="10"/>
<!-- Table header -->
<pdf:style fontsize="9" fontstyle="B" bgcolor="#F0F0F0"
border="TB" borderwidth="0.5" padding="2">
<pdf:row>
<pdf:col width="80">Description</pdf:col>
<pdf:col width="25">Qty</pdf:col>
<pdf:col width="35">Unit Price</pdf:col>
<pdf:col width="30">Total</pdf:col>
</pdf:row>
</pdf:style>
<!-- Line items -->
<pdf:style fontsize="9" padding="2">
<pdf:row>
<pdf:col width="80">Enterprise License</pdf:col>
<pdf:col width="25">1</pdf:col>
<pdf:col width="35">1,200.00</pdf:col>
<pdf:col width="30">1,200.00</pdf:col>
</pdf:row>
<pdf:style bgcolor="#FAFAFA">
<pdf:row>
<pdf:col width="80">Support Package</pdf:col>
<pdf:col width="25">1</pdf:col>
<pdf:col width="35">300.00</pdf:col>
<pdf:col width="30">300.00</pdf:col>
</pdf:row>
</pdf:style>
<pdf:row>
<pdf:col width="80">Training Sessions</pdf:col>
<pdf:col width="25">3</pdf:col>
<pdf:col width="35">150.00</pdf:col>
<pdf:col width="30">450.00</pdf:col>
</pdf:row>
</pdf:style>
<!-- Total -->
<pdf:style fontsize="10" fontstyle="B" border="T" borderwidth="0.5" padding="2">
<pdf:row>
<pdf:col width="140">Total</pdf:col>
<pdf:col width="30">1,950.00</pdf:col>
</pdf:row>
</pdf:style>
<!-- QR code for payment -->
<pdf:linebreak offset="15"/>
<pdf:barcode type="QRCODE,M" width="30" height="30">PAY-INV-2024-001</pdf:barcode>
</pdf:body>
</pdf:section>
</pdf:document>
Dynamic Table with Page Break Control
This pattern shows how to handle variable-length data with automatic page breaks:
<pdf:body>
<foreach var="items" var_value="item">
<!-- Check remaining space before each row -->
<pdf:getpos var_y="y"/>
<if value1="$y" value2="260" func=">">
<pdf:pagebreak/>
<pdf:linebreak offset="5"/>
<!-- Repeat table header on new page -->
<pdf:style fontsize="9" fontstyle="B" border="B" borderwidth="0.5">
<pdf:row>
<pdf:col width="80">Item</pdf:col>
<pdf:col width="30">Qty</pdf:col>
<pdf:col width="40">Price</pdf:col>
</pdf:row>
</pdf:style>
</if>
<pdf:style fontsize="9">
<pdf:row>
<pdf:col width="80">$item.name</pdf:col>
<pdf:col width="30">$item.qty</pdf:col>
<pdf:col width="40">$item.price</pdf:col>
</pdf:row>
</pdf:style>
</foreach>
</pdf:body>
Alternating Row Colors
<set var="row_index">0</set>
<foreach var="items" var_value="item">
<set var="bg"></set>
<if value1="$(($row_index % 2))" value2="0">
<set var="bg">#F8F8F8</set>
</if>
<pdf:style fontsize="9" bgcolor="$bg" valign="M">
<pdf:row>
<pdf:col width="80">$item.name</pdf:col>
<pdf:col width="40">$item.value</pdf:col>
</pdf:row>
</pdf:style>
<set var="row_index">$(($row_index + 1))</set>
</foreach>