How-to guides/XFA Forms

Fill XFA dynamic form fields with data in Rust

Write field values into the XFA datasets packet to populate a dynamic XFA form with application data.

rust
use pdfluent::Document;

fn main() -> pdfluent::Result<()> {
    let mut doc = Document::open("blank_form.pdf")?;

    {
        let xfa = doc.xfa_mut().ok_or(pdfluent::Error::NoXfa)?;
        let mut datasets = xfa.datasets_mut()?;

        datasets.set_field("form1.subform1.firstName", "Alice")?;
        datasets.set_field("form1.subform1.lastName", "Dupont")?;
        datasets.set_field("form1.subform1.dob", "1985-06-15")?;
    }

    doc.save("filled_form.pdf")?;
    Ok(())
}
Install:cargo add pdfluentDownload SDK →

Step by step

1

Open the blank XFA form

Open the template form file for mutation. The XFA structure must already exist; PDFluent cannot create an XFA template from scratch.

rust
let mut doc = Document::open("blank_form.pdf")?;
2

Get a mutable reference to the XFA datasets

xfa_mut() returns a mutable XFA handle. datasets_mut() parses the xfa:data XML into an editable tree.

rust
let xfa = doc.xfa_mut().ok_or(pdfluent::Error::NoXfa)?;
let mut datasets = xfa.datasets_mut()?;
3

Set individual field values

Field paths are dot-separated, following the XFA form hierarchy. The path must match a node in the template.

rust
datasets.set_field("form1.personal.firstName", "Alice")?;
datasets.set_field("form1.personal.lastName", "Dupont")?;
datasets.set_field("form1.personal.email", "[email protected]")?;
4

Fill multiple fields from a HashMap

For batch filling, pass a map of path -> value pairs.

rust
use std::collections::HashMap;

let mut values: HashMap<&str, &str> = HashMap::new();
values.insert("form1.address.street", "123 Main St");
values.insert("form1.address.city", "Amsterdam");
values.insert("form1.address.postcode", "1234AB");

for (path, value) in &values {
    datasets.set_field(path, value)?;
}
5

Save the filled form

The modified datasets XML is serialized back into the PDF. Save to a new file to preserve the original blank template.

rust
doc.save("filled_form.pdf")?;

Notes and tips

  • XFA field paths are case-sensitive. "form1.Name" and "form1.name" are different paths.
  • Date fields expect ISO 8601 format (YYYY-MM-DD) by default. Check the field binding in the XFA template if a different format is required.
  • For repeated subforms (table rows), use datasets.append_subform("form1.items") to add a new instance, then set fields on it.
  • XFA forms are rendered by the PDF viewer at display time. Saving filled data does not produce a static appearance; the viewer renders from the template and data.

Why PDFluent for this

Pure Rust

No JVM, no runtime, no DLL dependencies. Ships as a single native binary or WASM module.

Memory safe

Rust's ownership model prevents buffer overflows and use-after-free. No segfaults in PDF parsing.

Runs anywhere

Same code runs server-side, in Docker, on AWS Lambda, on Cloudflare Workers, or in the browser via WASM.

Frequently asked questions