pdg XML → PDF

Guide

Python

The pdg Python package — render an XML document to a PDF, or raise with the engine's diagnostics.

The pdg package renders a pdg XML document to PDF bytes in Python. The engine is packed into the wheel (one wheel bundles a prebuilt binary for every platform), so there's no toolchain to install and nothing to compile.

import pdg

data = pdg.render(open("invoice.xml").read(), base="invoices")
with open("invoice.pdf", "wb") as f:
    f.write(data)

The XML you pass is the document format documented throughout these guides — see Document structure and the element reference.

Python ≥ 3.8, with bundled type hints (PEP 561).

Installation

pip install pdg

Rendering

The document is str or bytes; base is a keyword-only asset directory (see Assets).

# PDF bytes. Raises on failure.
data = pdg.render(xml, base=".")

# Bytes plus metadata.
result = pdg.render_with_meta(xml)
result.pages      # 3
result.bytes      # 48213 (len(result.pdf))
result.objects    # 412
result.timings    # {"parseMs": 1.2, "layoutMs": 8.4, "pdfMs": 5.1}
result.warnings   # [Diagnostic, ...]
result.pdf        # bytes

# Straight to a file (returns the Result).
pdg.render_file(xml, "report.pdf", base="assets")

Assets

Relative paths inside the document — <font-face src>, <image src>, <pdf src> — resolve against base (default: the current working directory). http(s) URLs and <google-font> faces are fetched by the engine regardless.

pdg.render(xml, base="/srv/app/pdf_assets")

Errors and diagnostics

Every exception derives from pdg.PdgError.

  • pdg.RenderError — the engine withheld a PDF (a strict-mode block or a fatal parse/layout error); carries .diagnostics and the raw .meta.
  • pdg.BinaryError — the engine couldn't run (an installation/environment problem).
try:
    data = pdg.render(xml)
except pdg.RenderError as err:
    print(err)                  # headline plus each diagnostic, one per line
    for d in err.diagnostics:
        d.severity              # "warning" | "error"
        d.code                  # "unknown-tag", "content-dropped", …
        d.message
        d.line                  # 1-based source position (0 if none)
        d.col
        d.trace                 # enclosing tags, innermost first

Warnings don't raise — a recoverable render returns a Result; read result.warnings. Diagnostic exposes .is_warning / .is_error.

How it works

The package runs the packed engine over stdio (XML on stdin, PDF on stdout, one JSON meta object on stderr) behind one module, so the same engine that powers the CLI and this playground produces your PDFs. Set the PDG_BINARY environment variable to override the bundled binary. Renders are blocking; call them from a thread or executor to overlap them.