[英]How to use itext to fill out (dynamic XFA) PDF from data in a text file
我有一個本地PDF表單,該表單具有一個永不更改的特定模板。 由於沒有返回鍵集,因此我將表單標識為XFA(xml)動態表單。 我正在嘗試使用itext用.txt文件中包含的數據填寫表單。 根據我的理解,我需要以某種方式從文本文件中獲取數據並將其正確放置到.xml文件中,以便itext可以使用給定的xml來處理原始PDF。
表單具有以下布局作為示例:
我在Eclipse中使用的示例代碼可以成功編譯/運行,但需要使用data.xml
中的數據,以便使用字段數據填充空表單並輸出填充的版本。 問題是,對於我的實際項目,我沒有要正確填充表單的data.xml文件。 原始字段數據在.txt文件中,每行包含PDF中不同字段的數據。
示例:參考上面的圖像,我的.txt文件看起來像這樣,直到包含(包括)“ FOUR”的字段為止的字段:
我對兩件事感到困惑:
1.如何提取原始PDF的xml結構,以便在使用.txt文件中的數據填充時知道要遵循的格式?
2.如何從文本文件中獲取值並將其正確插入.xml結構中?
以下代碼有效,但需要data.xml
才能填寫“ incomplete.pdf”。 它使用代碼xfa.fillXfaForm(new FileInputStream(XML));
輸入數據,但是我一直堅持如何識別“ XML”的結構以及如何首先填充它。
任何幫助表示贊賞,非常感謝。
碼:
package sandbox;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.util.Set;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.TransformerFactoryConfigurationError;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.pdf.AcroFields;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfStamper;
import com.itextpdf.text.pdf.XfaForm;
public class FillXFA {
public static final String SRC = "C:/Workspace/PDF/incomplete.pdf";
public static final String XML = "C:/Workspace/PDF/data.xml";
public static final String DEST = "C:/Workspace/PDF/completed.pdf";
public static void main(String[] args) throws IOException, DocumentException {
File file = new File(DEST);
file.getParentFile().mkdirs();
new FillXFA().manipulatePdf(SRC, DEST);
}
public void readXfa(String src, String dest)
throws IOException, ParserConfigurationException, SAXException,
TransformerFactoryConfigurationError, TransformerException {
FileOutputStream os = new FileOutputStream(dest);
PdfReader reader = new PdfReader(src);
XfaForm xfa = new XfaForm(reader);
Document doc = xfa.getDomDocument();
Transformer tf = TransformerFactory.newInstance().newTransformer();
tf.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
tf.setOutputProperty(OutputKeys.INDENT, "yes");
tf.transform(new DOMSource(doc), new StreamResult(os));
reader.close();
}
public void manipulatePdf(String src, String dest)
throws IOException, DocumentException {
PdfReader reader = new PdfReader(src);
PdfStamper stamper = new PdfStamper(reader,
new FileOutputStream(dest));
AcroFields form = stamper.getAcroFields();
XfaForm xfa = form.getXfa();
xfa.fillXfaForm(new FileInputStream(XML));
stamper.close();
reader.close();
}
}
在XFA中,表單字段和表單數據之間的鏈接是使用稱為數據綁定的概念進行的。 字段可以具有類似XPath的表達式,以從XML數據結構中選擇其值。 這意味着需要對XML數據進行適當的結構化以使其適合特定的XFA格式,但是此結構不一定是唯一的。
一個簡單的示例:假設您有一個僅包含1個文本字段的XFA表單。 該文本字段具有綁定到標簽名稱為“ Name”的任何XML元素的數據。 在這種情況下,您的data.xml可以簡單地是:
<Name>Hurmle</Name>
但是,這和無數種不同的XML結構也將起作用:
<StackOverflow>
<accounts>
<account>
<Name>Hurmle</Name>
</account>
</accounts>
</StackOverflow>
您的代碼示例中的readXfa
方法將用於從XFA表單中提取完整的XML流。 它由不同部分組成。 最相關的是:
確定哪種XML結構將起作用的一種方法是查看所有字段的數據綁定(參見template )。 因此,您將知道這些字段期望從何處獲取其數據。 對於非平凡的形式,這可能很復雜和/或需要大量工作。
如果在XFA表單中可用,則可以使用dataDescription 。 它將為您提供數據和信息的結構,例如元素的最小和最大出現次數。
最后,您可以查看已經采用格式的數據 (參見xfa:data )。 請記住,此XML結構不一定完整:可以省略空元素。 例如,如果一個表單有2個字段,則值可以指定為:
<SomeRoot>
<Field1>Value1</Field1>
<Field2></Field2>
</SomeRoot>
但是也:
<SomeRoot>
<Field1>Value1</Field1>
</SomeRoot>
第一種情況將使您更容易找出所需的結構。 如果xfa:data丟失或不完整,您可以嘗試使用具有XFA功能的PDF查看器手動填寫所有表單字段。 保存時,查看器將根據數據描述和數據綁定填充xfa:data 。
供參考: XFA規范
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.