XFDF Felder mit C# lesen …

Adobe Forms Dokumente werden in verschiedenen Anwendungsfällen verwendet und es ist nicht unwahrscheinlich, dass man in einer Anwendung Daten aus solch einem Dokument übernehmen muss.

Adobe Forms können ihre Daten als FDF oder XFDF exportieren. Zum FDF Format gibt es ein Software SDK von Adobe. Liegen die Formsdaten als XFDF (= XML Forms Data Format) vor kann man die Daten mit Standard .NET Mitteln aus dem .XFDF File lesen, da es sich um eine XML Datei handelt. Die Grundstruktur jedes .XFDF Files sieht so aus und ist auch über ein Schema beschrieben.

<?xml version="1.0" encoding="UTF-8"?>

<xfdf xmlns="https://ns.adobe.com/xfdf/" xml:space="preserve">

<f href="Checklist.pdf"/>

<ids original="7A0631678ED475F0898815F0A818CFA1"

modified="BEF7724317B311718E8675B677EF9B4E"/>

<fields>

...

</fields>

</xfdf>

Da aber das Adobe XSD Schema sehr komplex ist, habe ich mir mit dem XSD.EXE Kommandozeilenprogramm aus einem existierenden .XFDF File eine eigene (De)-Serialisierungsklasse generiert (siehe Anhang), die auf die (De)-Serialisierung der Datenfelder optimiert ist. Danach kann man mit diesem einfachen Code, beliebige .XFDF Files lesen.

    private void ProcessTypedXfdfV1( string fileName )

      {

            XmlSerializer ser = new XmlSerializer( typeof( V1.xfdf ) );

            using ( StreamReader sr = File.OpenText( fileName ) )

            {

                V1.xfdf o = ser.Deserialize( sr ) as V1.xfdf;

                if ( o != null )

                {

                    foreach ( object of in o.Items )

                    {

                        System.Diagnostics.Trace.WriteLine( of );

                        if ( of is GenerateDDLfromXfdf.V1.xfdfFields )

                        {

                            V1.xfdfFields fields = of as V1.xfdfFields;

                            foreach ( V1.field f in fields.field )

                            {

                                ProcessV1Fields( f, string.Empty );

                            }

                        }

                    }

                }

            }

        }

Die Methode, die rekursiv den Inhalt der XFDF Datenfelder auswertet, sieht so aus.

        private void ProcessV1Fields( V1.field f, string parentFieldName )

        {

            if ( f != null )

            {

                System.Diagnostics.Trace.WriteLine( f.name + " = " + f.value + " (Parent = " + parentFieldName + ") " );

                if ( f.field1 != null )

                {

                    foreach ( V1.field f1 in f.field1 )

                    {

                        ProcessV1Fields( f1, (string.IsNullOrEmpty( parentFieldName ) ? string.Empty : parentFieldName + ".") + f.name );

                    }

                }

            }

        }

Die entsprechende Ausgabe im Visual Studio 2008 Debugfenster sieht so aus:

GenerateDDLfromXfdf.V1.xfdfFields

4 = Off (Parent = )

AMHeader = (Parent = )

AMSex = (Parent = AMHeader)

Female = Off (Parent = AMHeader.AMSex)

AMsex = (Parent = AMHeader)

Male = Off (Parent = AMHeader.AMsex)

B = Off (Parent = )

C = Off (Parent = )

Delete all = Delete ALL ITEMS (Parent = )

DeleteForm = Off (Parent = )

Enclose = Off (Parent = )

Enclosed = Off (Parent = )

Female = Off (Parent = )

LabeStateCountry = State/Country: (Parent = )

LabelEMail = E - Mail: (Parent = )

LabelName = Name (Parent = )

LabelPhone = Phone: (Parent = )

LabelStreet = Street: (Parent = )

LabelZipCity = Zip/City: (Parent = )

LenMedium = Off (Parent = )

No = Off (Parent = )

PageAMA0 = (Parent = )

AMCklContents = (Parent = PageAMA0)

CklContItems = (Parent = PageAMA0.AMCklContents)

EnclComplete = (Parent = PageAMA0.AMCklContents.CklContItems)

1 = Off (Parent = PageAMA0.AMCklContents.CklContItems.EnclComplete)

10 = Off (Parent = PageAMA0.AMCklContents.CklContItems.EnclComplete)

11 = Off (Parent = PageAMA0.AMCklContents.CklContItems.EnclComplete)

12 = Off (Parent = PageAMA0.AMCklContents.CklContItems.EnclComplete)

13 = Off (Parent = PageAMA0.AMCklContents.CklContItems.EnclComplete)

14 = Off (Parent = PageAMA0.AMCklContents.CklContItems.EnclComplete)

2 = Off (Parent = PageAMA0.AMCklContents.CklContItems.EnclComplete)

3 = Off (Parent = PageAMA0.AMCklContents.CklContItems.EnclComplete)

Das (De)-Serialisierungsfile findet Ihr im Anhang des Blogs.

Viel Spass beim Ausprobieren … Gunnar

V1.xfdf.cs