When processing digital documents, managing data efficiently and accurately is critical. XFDF (XML Forms Data Format) is an important format that simplifies data exchange for PDF forms. This article explores what XFDF is, its key features, and practical ways to use it in document workflows. It also shows how to export XFDF from an existing PDF document using TX Text Control, and how to import XFDF XML into a document to pre-select or populate form fields.

What is XFDF?

XFDF stands for XML Forms Data Format, a subset of Adobe's PDF specifications. It is an XML-based format that has been specifically designed to handle the data for PDF forms. XFDF files store form field data, annotations, or bookmarks associated with a PDF document, making it easy to extract, modify, or submit form data without altering the original PDF.

An XFDF file is structured in XML, which means it is human-readable and easy for developers to manipulate. It provides a standardized way to interact with the data in PDF forms, separating content from layout and presentation.

Here's an example of a simple XFDF file:

<?xml version="1.0" encoding="UTF-8"?>
<xfdf xmlns="http://ns.adobe.com/xfdf/">
<f href="form.pdf" />
<fields>
<field name="Name">
<value>TimTyper</value>
</field>
<field name="Email">
<value>tim@textcontrol.com</value>
</field>
</fields>
</xfdf>
view raw test.xml hosted with ❤ by GitHub
Element Attribute Content
fields Contains all form fields.
field name A form field with a name attribute.
value Represents the value entered into the form field.
f href Specifies the associated PDF file.

XFDF is widely used in workflows where the collection and processing of form data is essential. For example, a customer fills out a PDF form and the XFDF file stores the submitted data. This data can then be imported back into the form or sent to a database for processing. XFDF bridges the gap between PDF forms and databases. Form data stored in XFDF files can be parsed and stored in a database or vice versa, enabling dynamic and automated workflows.

XFDF files can dynamically populate forms. For example, a system can generate an XFDF file with customer data, and the data is merged into a PDF form to create a customized document.

How to Export XFDF from a PDF Document

The XfdfProcessing class implements methods to convert form fields imported from a PDF document to XFDF XML format and a method to parse existing XFDF XML to pre-select form fields. Consider the following PDF document with form fields.

PDF form fields

The following code snippet shows how to export XFDF from a PDF document using TX Text Control:

using TXTextControl;
using TXTextControl.DocumentServer.PDF;
using TXTextControl.DocumentServer.PDF.AcroForms.Xfdf;
var filePath = "forms.pdf";
// Extract form fields from the PDF
var formFields = Forms.GetAcroFormFields(filePath);
// Generate XFDF from the form fields
string xml = XfdfProcessing.GenerateXfdf(formFields, filePath);
Console.WriteLine(xml);
view raw test.cs hosted with ❤ by GitHub

The GetAcroFormFields TX Text Control .NET Server for ASP.NET
DocumentServer.PDF Namespace
Forms Class
GetAcroFormFields Method
Imports AcroFormFields from an Adobe PDF document.
method, which is part of the DocumentServer namespace, extracts all form fields from a PDF document. The GenerateXfdf method is included in the implemented XfdfProcessing class, which is listed below.

The output of the GenerateXfdf method is an XFDF XML string that can be saved to a file or sent to a server for further processing.

<?xml version="1.0" encoding="UTF-8"?><xfdf xml:space="preserve" xmlns="http://ns.adobe.com/xfdf/">
<f href="forms.pdf" />
<fields>
<field name="FormText1">
<value>Form Text</value>
</field>
<field name="FormCheck1">
<value>On</value>
</field>
<field name="FormCombo1">
<value>Item1</value>
</field>
<field name="FormDropDown1">
<value>Item2</value>
</field>
<field name="FormDate1">
<value>1/22/2025</value>
</field>
</fields>
<ids />
</xfdf>
view raw test.xml hosted with ❤ by GitHub

How to Import XFDF into a Document

Importing XFDF into a document is a common requirement in document workflows. The following code snippet shows how to import XFDF XML into a document with form fields using TX Text Control:

using TXTextControl;
using TXTextControl.DocumentServer.PDF;
using TXTextControl.DocumentServer.PDF.AcroForms.Xfdf;
var filePath = "forms.pdf";
// Extract form fields from the PDF
var formFields = Forms.GetAcroFormFields(filePath);
// Generate XFDF from the form fields
string xml = XfdfProcessing.GenerateXfdf(formFields, filePath);
var fields = XfdfProcessing.ParseXfdfFromXml(xml);
using (ServerTextControl tx = new ServerTextControl())
{
tx.Create();
tx.Load("forms.tx", StreamType.InternalUnicodeFormat);
// Convert the list to a dictionary
var dictionary = fields
.Where(field => field.Name != null) // Ensure Name is not null
.ToDictionary(field => field.Name!, field => field.Value);
// Merge the dictionary with the form fields
foreach (TXTextControl.FormField formField in tx.FormFields)
{
if (dictionary.ContainsKey(formField.Name))
{
switch (formField)
{
case CheckFormField checkBoxField:
checkBoxField.Checked = dictionary[formField.Name] == "On";
break;
default:
formField.Text = dictionary[formField.Name];
break;
}
}
}
tx.Save("results.tx", StreamType.InternalUnicodeFormat);
}
view raw test.cs hosted with ❤ by GitHub

The method ParseXfdfFromXml returns a list of form fields that can be used to pre-select or populate form fields in a PDF document. The form fields are then iterated and the values are set from the generated list.

The XfdfProcessing Class

The XfdfProcessing class is a helper class that provides methods to generate XFDF XML from a PDF document and to parse XFDF XML to pre-select form fields. The class is listed below:

using System.Xml.Linq;
namespace TXTextControl.DocumentServer.PDF.AcroForms.Xfdf
{
/// <summary>
/// Provides methods for processing and generating XFDF (XML Forms Data Format) documents.
/// </summary>
public class XfdfProcessing
{
/// <summary>
/// Generates an XFDF string for a set of form fields and associates it with a PDF filename.
/// </summary>
/// <param name="formFields">An array of form fields to include in the XFDF.</param>
/// <param name="filename">The filename of the associated PDF document.</param>
/// <returns>A string containing the generated XFDF XML.</returns>
public static string GenerateXfdf(FormField[] formFields, string filename)
{
if (formFields == null || formFields.Length == 0)
{
throw new ArgumentException("Form fields cannot be null or empty.", nameof(formFields));
}
if (string.IsNullOrEmpty(filename))
{
throw new ArgumentException("Filename cannot be null or empty.", nameof(filename));
}
var xfdfFields = new List<XfdfField>();
foreach (var formField in formFields)
{
// Process different types of form fields
var xfdfField = CreateXfdfField(formField);
if (xfdfField != null)
{
xfdfFields.Add(xfdfField);
}
}
return GenerateXfdfXml(xfdfFields, filename);
}
/// <summary>
/// Creates an XFDF field representation for a given form field.
/// </summary>
/// <param name="formField">The form field to process.</param>
/// <returns>An XFDF field object or null if the form field type is unsupported.</returns>
private static XfdfField? CreateXfdfField(FormField formField)
{
if (formField == null)
{
throw new ArgumentNullException(nameof(formField), "Form field cannot be null.");
}
return formField switch
{
FormTextField textField => new XfdfField
{
Name = textField.FieldName,
Value = textField.Value
},
FormCheckBox checkBox => new XfdfField
{
Name = checkBox.FieldName,
Value = checkBox.IsChecked ? "On" : "Off"
},
FormComboBox comboBox => new XfdfField
{
Name = comboBox.FieldName,
Value = comboBox.Value
},
FormChoiceField choiceField => new XfdfField
{
Name = choiceField.FieldName,
Value = choiceField.Value
},
_ => null // Unsupported form field type
};
}
/// <summary>
/// Parses an XFDF XML string to generate a list of XFDF fields.
/// </summary>
/// <param name="xmlContent">The XFDF XML content to parse.</param>
/// <returns>A list of XFDF fields extracted from the XML.</returns>
public static List<XfdfField> ParseXfdfFromXml(string xmlContent)
{
if (string.IsNullOrEmpty(xmlContent))
{
throw new ArgumentException("XML content cannot be null or empty.", nameof(xmlContent));
}
var fields = new List<XfdfField>();
XNamespace ns = "http://ns.adobe.com/xfdf/";
try
{
var document = XDocument.Parse(xmlContent);
var fieldElements = document.Root?.Element(ns + "fields")?.Elements(ns + "field");
if (fieldElements != null)
{
foreach (var fieldElement in fieldElements)
{
var name = fieldElement.Attribute("name")?.Value;
var value = fieldElement.Element(ns + "value")?.Value;
if (!string.IsNullOrEmpty(name))
{
fields.Add(new XfdfField
{
Name = name,
Value = value
});
}
}
}
}
catch (Exception ex)
{
throw new InvalidOperationException("Failed to parse XFDF XML.", ex);
}
return fields;
}
/// <summary>
/// Generates the XML for the XFDF document.
/// </summary>
/// <param name="fields">The fields to include in the XFDF.</param>
/// <param name="pdfHref">The associated PDF file href.</param>
/// <returns>A string containing the XFDF XML.</returns>
private static string GenerateXfdfXml(List<XfdfField> fields, string pdfHref)
{
// Define the XFDF namespace
XNamespace ns = "http://ns.adobe.com/xfdf/";
// Create the root XFDF element
var xfdf = new XElement(ns + "xfdf",
new XAttribute(XNamespace.Xml + "space", "preserve"),
new XElement(ns + "f", new XAttribute("href", pdfHref)),
new XElement(ns + "fields",
fields.Select(field =>
{
var fieldElement = new XElement(ns + "field", new XAttribute("name", field.Name));
if (!string.IsNullOrEmpty(field.Value))
{
fieldElement.Add(new XElement(ns + "value", field.Value));
}
return fieldElement;
})
),
new XElement(ns + "ids") // Placeholder for IDs
);
// Return the formatted XML string
return new XDeclaration("1.0", "UTF-8", null) + xfdf.ToString();
}
/// <summary>
/// Represents an XFDF field with a name and value.
/// </summary>
public class XfdfField
{
public string? Name { get; set; }
public string? Value { get; set; }
}
}
}
view raw test.cs hosted with ❤ by GitHub

Conclusion

XFDF is a powerful format that simplifies data exchange for PDF forms. It provides a standardized way to interact with form field data, making it easy to extract, modify, or submit form data without modifying the original PDF. XFDF is widely used in workflows where the capture and processing of form data is critical. It bridges the gap between PDF forms and databases, enabling dynamic and automated workflows.