Read the XFA data packet from a dynamic XFA form and access field values as typed Rust data.
use pdfluent::Document;
fn main() -> pdfluent::Result<()> {
let doc = Document::open("form.pdf")?;
let xfa = doc.xfa().ok_or(pdfluent::Error::NoXfa)?;
let datasets = xfa.datasets()?;
// Read a field value by its fully-qualified name
let first_name = datasets.field_value("form1.subform1.firstName")?;
println!("First name: {}", first_name.as_str().unwrap_or(""));
Ok(())
}doc.xfa() returns an Option<XfaDocument>. If the PDF does not contain an XFA structure, it returns None.
let doc = Document::open("form.pdf")?;
let xfa = doc.xfa().ok_or(pdfluent::Error::NoXfa)?;XFA forms store submitted data in the xfa:datasets XML packet. xfa.datasets() parses that XML into a queryable tree.
let datasets = xfa.datasets()?;Field names are dot-separated paths from the root node. The path mirrors the XFA form template hierarchy.
let val = datasets.field_value("form1.subform1.firstName")?;
match val {
pdfluent::xfa::FieldValue::Str(s) => println!("string: {}", s),
pdfluent::xfa::FieldValue::Date(d) => println!("date: {:?}", d),
pdfluent::xfa::FieldValue::Num(n) => println!("number: {}", n),
pdfluent::xfa::FieldValue::Empty => println!("(empty)"),
}Use datasets.fields() to get every leaf node in the data tree.
for field in datasets.fields() {
println!("{} = {:?}", field.path(), field.value());
}If you need the raw XML for custom processing, access the bytes directly.
let xml_bytes = datasets.to_xml_bytes()?;
std::fs::write("form_data.xml", &xml_bytes)?;No JVM, no runtime, no DLL dependencies. Ships as a single native binary or WASM module.
Rust's ownership model prevents buffer overflows and use-after-free. No segfaults in PDF parsing.
Same code runs server-side, in Docker, on AWS Lambda, on Cloudflare Workers, or in the browser via WASM.