Skip to main content

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:

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

Full reference ->

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

Full reference ->

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.

Full reference ->

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.

Full reference ->

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

Full reference ->

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.

Full reference ->

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.

Full reference ->

note

When using html="t", HTML tags must be XML-escaped (e.g., &lt;b&gt; 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.

Full reference ->

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.

Full reference ->

pdf:col

Defines a column within a pdf:row. Each column has its own width, and supports html, nowrap, and height.

Full reference ->

tip

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.

Full reference ->

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.

Full reference ->

Page Flow Control

pdf:linebreak

Adds vertical spacing by the given offset (in document units).

Full reference ->

pdf:pagebreak

Forces a new page. Optionally shifts the ordinate to a given offset on the new page.

Full reference ->

warning

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.

Full reference ->

note

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.

Full reference ->

pdf:setpos

Sets the current drawing position explicitly via page, x, and y. Enables absolute positioning and overlay effects.

Full reference ->


Practical Patterns

Minimal Document

XML
<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

XML
<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>
tip

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:

XML
<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:

XML
<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="&gt;">
<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

XML
<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>