# Export XFDF

> Export the values of PDF forms as XFDF with GetAcroFormFields and System.Xml.Linq, and fill a TX Text Control form template from an XFDF file again.

- **Product:** TX Text Control .NET Server
- **Section:** Documentation
- **Kind:** Topic
- **Path:** TX Text Control .NET Server > PDF Processing > PDF Forms > Export XFDF
- **3876 words**
- **Web URL:** https://docs.textcontrol.com/tx-text-control-dotnet-server/pdf/forms/export-xfdf/
- **LLMs URL:** https://docs.textcontrol.com/tx-text-control-dotnet-server/pdf/forms/export-xfdf/llms.txt
- **LLMs-Full URL:** https://docs.textcontrol.com/tx-text-control-dotnet-server/pdf/forms/export-xfdf/llms-full.txt

---

XFDF, the XML Forms Data Format, stores the values of a PDF form as XML, apart from the form itself. An XFDF file names the PDF document it belongs to and lists each field with its value, so systems can exchange form data, store it in a database or fill a form with it later. TX Text Control has no XFDF classes of its own: you create XFDF with `System.Xml.Linq` from the values that `Forms.GetAcroFormFields` returns, and you read it the same way to fill a form template.

How `GetAcroFormFields` returns the values of each field type is described in [Import Form Data](https://docs.textcontrol.com/tx-text-control-dotnet-server/pdf/forms/import-data/llms-full.txt). The examples use *Documents/order-form-filled.pdf*, the order form of [Form Fields](https://docs.textcontrol.com/tx-text-control-dotnet-server/document-processing/form-fields/#create-a-fillable-form) after a customer filled it in.

### How an XFDF File Is Built

XFDF is a part of Adobe's PDF specifications. A file with the values of the order form looks like this:

```xml
<?xml version="1.0" encoding="UTF-8"?>
<xfdf xml:space="preserve" xmlns="http://ns.adobe.com/xfdf/">
  <f href="order-form-filled.pdf" />
  <fields>
    <field name="Customer">
      <value>Acme Corporation</value>
    </field>
    <field name="Product">
      <value>Priority Support - 12 Months</value>
    </field>
    <field name="TermsAccepted">
      <value>On</value>
    </field>
  </fields>
</xfdf>
```

| Element | Attribute | Content |
|---|---|---|
| `xfdf` | `xmlns` | The root element, in the namespace `http://ns.adobe.com/xfdf/` |
| `f` | `href` | The PDF document the values belong to |
| `fields` |  | All form fields |
| `field` | `name` | One form field, identified by its name |
| `value` |  | The value entered into the form field |

XFDF can also hold annotations and bookmarks of a PDF document. The examples below write and read form field values only.

### Export the Values of a PDF Form

The following *Program.cs* reads the fields of the filled order form and saves their values as *Documents/order-form-filled.xfdf*:

```csharp
using System.Xml.Linq;
using TXTextControl.DocumentServer.PDF;
using TXTextControl.DocumentServer.PDF.AcroForms;

string pdfPath = "Documents/order-form-filled.pdf";
FormField[] fields = Forms.GetAcroFormFields(pdfPath);

XNamespace xfdfNamespace = "http://ns.adobe.com/xfdf/";
XElement fieldsElement = new XElement(xfdfNamespace + "fields");
HashSet<string> names = new HashSet<string>();

foreach (FormField field in fields)
{
    string? value;

    switch (field)
    {
        case FormTextField textField:
            value = textField.Value;
            break;

        case FormRadioButton:
            // The selected option of a radio group isn't available
            continue;

        case FormCheckBox checkBox:
            value = checkBox.IsChecked ? "On" : "Off";
            break;

        case FormChoiceField choiceField:   // combo boxes and list boxes
            value = choiceField.Value;
            break;

        default:                            // push buttons have no value
            continue;
    }

    // A name can occur more than once: write it once
    if (!names.Add(field.FieldName))
    {
        continue;
    }

    XElement fieldElement = new XElement(xfdfNamespace + "field", new XAttribute("name", field.FieldName));

    if (!string.IsNullOrWhiteSpace(value))
    {
        fieldElement.Add(new XElement(xfdfNamespace + "value", value));
    }

    fieldsElement.Add(fieldElement);
}

XDocument xfdf = new XDocument(
    new XDeclaration("1.0", "UTF-8", null),
    new XElement(xfdfNamespace + "xfdf",
        new XAttribute(XNamespace.Xml + "space", "preserve"),
        new XElement(xfdfNamespace + "f", new XAttribute("href", Path.GetFileName(pdfPath))),
        fieldsElement));

xfdf.Save("Documents/order-form-filled.xfdf");
Console.WriteLine(xfdf);
```

The code works as follows:

- [Forms.GetAcroFormFields](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol-documentserver-pdf/forms/getacroformfields-method/llms-full.txt) returns the fields of the PDF. Each type provides its value differently: [FormTextField.Value](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol-documentserver-pdf/acroforms-formtextfield/value-property/llms-full.txt) holds the text, [FormCheckBox.IsChecked](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol-documentserver-pdf/acroforms-formcheckbox/ischecked-property/llms-full.txt) the state and [FormChoiceField.Value](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol-documentserver-pdf/acroforms-formchoicefield/value-property/llms-full.txt) the selected item.
- A check box is written as `On` or `Off`, the names of the two states in PDF forms that TX Text Control creates. PDF forms created with other tools can name the checked state differently, for example `Yes`.
- [FormRadioButton](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol-documentserver-pdf/acroforms-formradiobutton/llms-full.txt) is tested before `FormCheckBox`, from which it derives, and skipped, because no member tells which option of the group is selected. Push buttons have no value and are skipped as well.
- The `HashSet` writes each field name once, because a name can occur several times in the array. A field without a value gets a `field` element without a `value` element.
- A date form field of TX Text Control is a text field in the PDF, so its date is written as the text the form displayed.

To offer the export in a web application, read the uploaded PDF with the byte array overload of `GetAcroFormFields`, as [Accept Uploaded Forms in ASP.NET Core](https://docs.textcontrol.com/tx-text-control-dotnet-server/pdf/forms/import-data/#accept-uploaded-forms-in-asp-net-core) shows, and return the XFDF document instead of JSON.

### Fill a Form Template From XFDF

TX Text Control doesn't apply XFDF to an existing PDF. To create a PDF with the values of an XFDF file, fill your template of the form and save it. The following program reads *Documents/order-form-filled.xfdf*, fills *Documents/order-form.tx* and saves the result as a fillable PDF:

```csharp
using System.Globalization;
using System.Xml.Linq;
using TXTextControl;

XNamespace xfdfNamespace = "http://ns.adobe.com/xfdf/";
XDocument xfdf = XDocument.Load("Documents/order-form-filled.xfdf");

// Field name and value; a field without a value element gets an empty string
Dictionary<string, string> values = new Dictionary<string, string>();

foreach (XElement field in xfdf.Root?.Element(xfdfNamespace + "fields")?.Elements(xfdfNamespace + "field")
                           ?? Enumerable.Empty<XElement>())
{
    string? name = field.Attribute("name")?.Value;

    if (!string.IsNullOrEmpty(name))
    {
        values[name] = field.Element(xfdfNamespace + "value")?.Value ?? string.Empty;
    }
}

using (ServerTextControl tx = new ServerTextControl())
{
    tx.Create();
    tx.Load("Documents/order-form.tx", StreamType.InternalUnicodeFormat);

    // The main text, text frames, headers and footers
    foreach (IFormattedText textPart in tx.TextParts)
    {
        foreach (FormField formField in textPart.FormFields)
        {
            if (string.IsNullOrEmpty(formField.Name) || !values.TryGetValue(formField.Name, out string? value))
            {
                continue;
            }

            switch (formField)
            {
                case CheckFormField checkFormField:
                    checkFormField.Checked = value == "On";
                    break;

                case SelectionFormField selectionFormField:
                    // -1 selects nothing if the value isn't one of the items
                    selectionFormField.SelectedIndex = Array.IndexOf(selectionFormField.Items, value);
                    break;

                case DateFormField dateFormField:
                    // Parse the date with the culture the form displays it in
                    dateFormField.Date = DateTime.TryParse(value, CultureInfo.GetCultureInfo("en-US"),
                        DateTimeStyles.None, out DateTime date) ? date : null;
                    break;

                default:
                    if (!string.IsNullOrWhiteSpace(value))
                    {
                        formField.Text = value;
                    }
                    break;
            }
        }
    }

    tx.Save("Documents/order-form-from-xfdf.pdf", StreamType.AdobePDF);
}
```

The code works as follows:

- `XDocument.Load` reads the XFDF file, and the loop collects the `name` attribute and the `value` element of each `field` in the XFDF namespace.
- The loop over the form fields of all text parts sets each value through the property of its form field type, as in [Transfer the Values Into a Form Template](https://docs.textcontrol.com/tx-text-control-dotnet-server/pdf/forms/import-data/#transfer-the-values-into-a-form-template). A check box is checked when its XFDF value is `On`.
- `StreamType.AdobePDF` saves a fillable PDF with the values. Flatten the fields before saving to fix the values, as [Flatten Forms](https://docs.textcontrol.com/tx-text-control-dotnet-server/pdf/forms/flatten/llms-full.txt) describes.

The blog article [Export and Import Adobe PDF XFDF XML Files in .NET C#](https://www.textcontrol.com/blog/2025/01/22/export-and-import-adobe-pdf-xfdf-xml-files-in-net-c-sharp/) explains XFDF and packages the export and import in a helper class, `XfdfProcessing`. The class is sample code of the article and not part of TX Text Control. It's available in the [XfdfProcessing](https://github.com/TextControl/XfdfProcessing) repository on GitHub.

### Next Steps

- [Import Form Data](https://docs.textcontrol.com/tx-text-control-dotnet-server/pdf/forms/import-data/llms-full.txt): read the values of filled PDF forms as JSON or a C# model.
- [Flatten Forms](https://docs.textcontrol.com/tx-text-control-dotnet-server/pdf/forms/flatten/llms-full.txt): turn a filled form template into a document with fixed values.
- [AcroForms](https://docs.textcontrol.com/tx-text-control-dotnet-server/pdf/forms/acroforms/llms-full.txt): create the PDF forms whose data you export.

---

## Nearby

- **Previous:** [Import Form Data](https://docs.textcontrol.com/tx-text-control-dotnet-server/pdf/forms/import-data/llms-full.txt)
- **Next:** [Flatten Forms](https://docs.textcontrol.com/tx-text-control-dotnet-server/pdf/forms/flatten/llms-full.txt)
