简体   繁体   中英

How to fill a single field of an XFA pdf document?

My Pdf contains an XFA form with an empty field. I tried filling it by manipulating the XML then applying SetXfa() with ITextSharp, but the PDF does not change. Here is my method :

static void EditFieldXFA(string path, string key, string value)
{
    iTextSharp.text.pdf.PdfReader reader = new iTextSharp.text.pdf.PdfReader(path);
    using (MemoryStream ms = new MemoryStream())
    {
        PdfStamper stamper = new PdfStamper(reader, ms);
        AcroFields form = stamper.AcroFields;
        XfaForm xfa = form.Xfa;
        var a = xfa.DatasetsNode.InnerXml;
        if (a.Contains(key))
        {
            // The empty XML looks like <key />, and a filled XML looks like <key>value</key>, so we edit the field
            string keyClose = key.Replace(" /", "").Replace("<", "</");
            var newXml = a.Replace(key, key.Replace(" /", "") + value + keyClose);
            XmlDocument doc = new XmlDocument();
            doc.LoadXml(newXml);
            // xfa.FillXfaForm(XmlReader.Create(new StringReader(newXml)));
            xfa.DomDocument = doc;
            xfa.Changed = true;
            XfaForm.SetXfa(xfa, stamper.Reader, stamper.Writer);

            stamper.Close();
            reader.Close();

            return;
        }
        else
        {
            Console.Write("Error : No " + key + " field detected. Please check that it is empty. Press enter to exit the process.");
            Console.Read();
            Environment.Exit(2);
        }
    }
}

The XML is correctly modified, I checked. Is this the correct way ? Do you have any idea what to try next ? Thank you for your help !

XML file : https://drive.google.com/file/d/1EbZJM6TjZ5tXQ0Dxa6IeUDz3QgJuxsBi/view?usp=sharing Please let me know if there's any issue with the download, and open it in Acrobat to see the content.

General issues

The stream your PdfStamper writes to is the MemoryStream ms

PdfStamper stamper = new PdfStamper(reader, ms);

and you completely ignore its contents after closing the stamper, ie finishing the stamping

stamper.Close();
reader.Close();

return;

Thus, your changes are lost.

Instead you can return the manipulated PDF as byte array to the caller, simply declare the method return type as byte[]

static byte[] EditFieldXFA(string path, string key, string value)

and return the memory stream contents

stamper.Close();
reader.Close();

return ms.ToArray();

Specific XML changing issues

Whenever you want to manipulate a XML file, don't do it manually, use a XML API , eg DOM; every once in a while a situation pops up in which building XML manually appears simpler but usually that appearance is deceptive, you eventually get into trouble for doing so.

In particular in the case at hand you already have a XmlNode : xfa.DatasetsNode . You can simply set all its children with a given name like this:

static byte[] EditFieldXFAImproved(string path, string xpath, string value)
{
    iTextSharp.text.pdf.PdfReader reader = new iTextSharp.text.pdf.PdfReader(path);
    using (MemoryStream ms = new MemoryStream())
    {
        PdfStamper stamper = new PdfStamper(reader, ms);
        AcroFields form = stamper.AcroFields;
        XfaForm xfa = form.Xfa;
        XmlNode a = xfa.DatasetsNode;
        XmlNodeList hits = a.SelectNodes(xpath);
        foreach(XmlNode hit in hits)
        {
            if (hit.NodeType == XmlNodeType.Element)
            {
                hit.InnerText = value;
            }
        }
        xfa.Changed = true;
        stamper.Close();
        reader.Close();

        return ms.ToArray();
    }
}

For example

byte[] result = EditFieldXFAImproved(@"53116504000001 (3).pdf", "//Grund", "Gruuuuuuund");
File.WriteAllBytes(@"53116504000001 (3)-filled.pdf", result);

sets the "Ablehnungsgrund/Hinweis" field value to "Gruuuuuuund".

Beware, the second parameter has been renamed from key to xpath because now it is not expected to contain an empty XML element "<key />" anymore but instead an xpath "//key" .


Was ist denn das, was da plötzlich so schnell auf mich zukommt? So sehr, sehr schnell. So riesig und so flach und so rund. Das braucht einen riesigen Namen … wie …. Grund!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM