使用iTextSharp以编程方式更改字段的PDF(动态XFA)在打开时会引发SOM错误

时间:2019-07-09 21:58:00

标签: c# itext

使用iText方法pdfStamper.AcroFields.SetField(“ target”,“ value”)会将“ target”字段设置为所需的“ value”。但是,在Reader中打开后,生成的PDF会引发SOM表达式错误。

使用AcroFields.Xfa.FindDatasetsNode(“ target”),创建并附加一个文本节点(例如node.OwnerDocument.CreateTextNode(“ new text”)),然后附加到找到的节点(例如foundNode)的代码.AppendChild(text),也会失败。

我唯一能做的就是保存整个PDF DOM(例如,doc = pdfReader.AcroFields.Xfa.DomDocument; doc.Save(writer)),然后将该DOM加载到另一个变量中,对其进行修改,然后将其保存回pdfStamp.AcroFields.Xfa.DomDocument。

但是,我最终得到一个禁用了“扩展功能”的PDF-尽管在打开压模时我使用的是“附加模式”(例如pdfStamp = new PdfStamper(pdfReader,pdfStampMS,'\ 0' , true )。

代码如下:

using System;
using iTextSharp;
using iTextSharp.text;
using iTextSharp.text.pdf;
using iTextSharp.text.xml;
using System.IO;
using System.Text;
using System.Xml;

string srcPDF = "c:\\Temp\\PDF\\A3.pdf";
string destPDF = "c:\\Temp\\PDF\\A3-out10.pdf";

PdfReader pdfReader = new PdfReader(srcPDF);    
MemoryStream pdfStampMS = new MemoryStream();
PdfStamper pdfStamp = null;
pdfStamp = new PdfStamper(pdfReader, pdfStampMS, '\0', true);

AcroFields form = pdfStamp.AcroFields;
string s = form.GetField("us - request[0].ContentArea1[0].sfApplicantInformation[0].sfApplicantName[0].firstName[0]");
//Checking, and this does get the value
form.SetField("us - request[0].ContentArea1[0].sfApplicantInformation[0].sfApplicantName[0].firstName[0]", "XYZtest");
s = form.GetField("us - request[0].ContentArea1[0].sfApplicantInformation[0].sfApplicantName[0].firstName[0]");
//Checking again, and this does set the value
pdfStamp.AcroFields.Xfa.Changed = true;
pdfStamp.AcroFields.Xfa.FillXfaForm(pdfStamp.AcroFields.Xfa.DatasetsNode, true);
pdfStamp.Close();
byte[] content = pdfStampMS.ToArray();
using (var fs = File.Create(destPDF))
{
fs.Write(content, 0, (int)content.Length);
}
pdfReader.Close();

所请求的字段被设置为所需的值,但是在打开时,结果PDF引发此异常:“字段'sfAssigneeEmail'上指定的datRef的SOM表达式'sfAssigneeEmail'被解析为'dataValue'的不兼容节点类型。”

“扩展功能”也被禁用。

有很多这样的问题,关于“扩展功能”问题的大多数答案只是简单地指出“使用附加模式”(我相信我正在这样做)。更麻烦的是这种格式不正确的PDF会创建-我还没有看到有人指出问题。

任何帮助或建议,不胜感激!

更新

我发现了问题,并且像往常一样,对我而言这只是简单的无知。我从来没有真正理解过什么代码:

pdfStamp.AcroFields.Xfa.FillXfaForm(pdfStamp.AcroFields.Xfa.DatasetsNode, true);

是为。我认为让pdfStamper发挥作用是某种神奇的咒语。它不是。实际上,它是一个非常有用的野兽,它允许您根据提供的XML文档自动更改字段。

一旦我意识到这一点,解决方法就显而易见了:删除该行代码 (例如pdfStamp.AcroFields.Xfa.FillXfaForm(pdfStamp.AcroFields.Xfa.DatasetsNode,true))行。这样做,一切都很棒。

修改后的代码如下:

using System;
using iTextSharp;
using iTextSharp.text;
using iTextSharp.text.pdf;
using iTextSharp.text.xml;
using System.IO;
using System.Text;
using System.Xml;

string srcPDF = "c:\\Temp\\PDF\\Input.pdf";
string destPDF = "c:\\Temp\\PDF\\Output.pdf";

PdfReader pdfReader = new PdfReader(srcPDF);    
MemoryStream pdfStampMS = new MemoryStream();
PdfStamper pdfStamp = null;
pdfStamp = new PdfStamper(pdfReader, pdfStampMS, '\0', true);

AcroFields form = pdfStamp.AcroFields;
string s = form.GetField("us - request[0].ContentArea1[0].sfApplicantInformation[0].sfApplicantName[0].firstName[0]");
//Checking, and this does get the value
form.SetField("us - request[0].ContentArea1[0].sfApplicantInformation[0].sfApplicantName[0].firstName[0]", "XYZtest");
s = form.GetField("us - request[0].ContentArea1[0].sfApplicantInformation[0].sfApplicantName[0].firstName[0]");
//Checking again, and this does set the value
pdfStamp.AcroFields.Xfa.Changed = true;
pdfStamp.Close();
byte[] content = pdfStampMS.ToArray();
using (var fs = File.Create(destPDF))
{
fs.Write(content, 0, (int)content.Length);
}
pdfReader.Close();

0 个答案:

没有答案