如何使用 iText 填写 XFA 表单使其与 Foxit Reader 兼容
How to fill XFA from using iText so it is Foxit Reader comptible
我使用网络上可用的示例创建了一个应用程序,该应用程序能够获取 xml XFA 表单的结构,然后将其设置回填充。重要代码如下所示:
public void readData(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);
Node node = xfa.getDatasetsNode();
NodeList list = node.getChildNodes();
for (int i = 0; i < list.getLength(); i++) {
if ("data".equals(list.item(i).getLocalName())) {
node = list.item(i);
break;
}
}
Transformer tf = TransformerFactory.newInstance().newTransformer();
tf.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
tf.setOutputProperty(OutputKeys.INDENT, "yes");
tf.transform(new DOMSource(node), new StreamResult(os));
reader.close();
}
public void fillPdfWithXmlData(String src, String xml, String dest)
throws IOException, DocumentException {
PdfReader.unethicalreading = true;
PdfReader reader = new PdfReader(src);
PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(dest), '[=11=]', true);
AcroFields form = stamper.getAcroFields();
XfaForm xfa = form.getXfa();
xfa.fillXfaForm(new FileInputStream(xml));
stamper.close();
reader.close();
}
当我使用它来填写此表格时:http://www.vzp.cz/uploads/document/tiskopisy-pro-zamestnavatele-hromadne-oznameni-zamestnavatele-verze-2-pdf-56-kb.pdf 它工作正常,我可以在 Acrobat Reader 中看到填写的表格。但是,如果我在 Foxit Reader 中打开文档,我会看到一个空白表格(在最新版本和 5.x 版本中测试过)。
我试着玩了一下,得到了这些 XfaForm(...).getDomDocument()
数据:
由 Acrobat 填充 Reader:http://pastebin.com/kXKyh9EM
由 Foxit 填充 Reader:http://pastebin.com/tiZ7EmfE
由 iText 填充:http://pastebin.com/tTKLMERC
在 iText 填充后由 Foxit Reader 填充:http://pastebin.com/Uuq0jS4b
填写的字段是 。是否有可能以与 Foxit 一起工作的方式使用 iText Reader(并且 XFA 签名保留?)
在您的 Filled by iText 示例中,有一个多余的 <xfa:data>
元素:
<xfa:datasets xmlns:xfa="http://www.xfa.org/schema/xfa-data/1.0/">
<xfa:data>
<xfa:data>
<HOZ>
<!-- rest of your data here -->
</HOZ>
</xfa:data>
</xfa:data>
<!-- data description -->
</xfa:datasets>
这是因为 XfaForm
的 fillXfaForm()
方法需要没有 <xfa:data>
的 XML 数据作为根元素。所以你的 XML 数据应该看起来像:
<HOZ>
<!-- rest of your data here -->
</HOZ>
我看到您的 readData()
方法提取现有表单数据,包括 <xfa:data>
元素:
<xfa:data>
<HOZ>
<!-- rest of your data here -->
</HOZ>
</xfa:data>
剥离外部元素应该可以解决您的问题。例如:
XfaForm xfa = new XfaForm(reader);
Node node = xfa.getDatasetsNode();
NodeList list = node.getChildNodes();
for (int i = 0; i < list.getLength(); i++) {
if ("data".equals(list.item(i).getLocalName())) {
node = list.item(i);
break;
}
}
// strip <xfa:data>
node = node.getFirstChild();
// Transformer code here
我使用网络上可用的示例创建了一个应用程序,该应用程序能够获取 xml XFA 表单的结构,然后将其设置回填充。重要代码如下所示:
public void readData(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);
Node node = xfa.getDatasetsNode();
NodeList list = node.getChildNodes();
for (int i = 0; i < list.getLength(); i++) {
if ("data".equals(list.item(i).getLocalName())) {
node = list.item(i);
break;
}
}
Transformer tf = TransformerFactory.newInstance().newTransformer();
tf.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
tf.setOutputProperty(OutputKeys.INDENT, "yes");
tf.transform(new DOMSource(node), new StreamResult(os));
reader.close();
}
public void fillPdfWithXmlData(String src, String xml, String dest)
throws IOException, DocumentException {
PdfReader.unethicalreading = true;
PdfReader reader = new PdfReader(src);
PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(dest), '[=11=]', true);
AcroFields form = stamper.getAcroFields();
XfaForm xfa = form.getXfa();
xfa.fillXfaForm(new FileInputStream(xml));
stamper.close();
reader.close();
}
当我使用它来填写此表格时:http://www.vzp.cz/uploads/document/tiskopisy-pro-zamestnavatele-hromadne-oznameni-zamestnavatele-verze-2-pdf-56-kb.pdf 它工作正常,我可以在 Acrobat Reader 中看到填写的表格。但是,如果我在 Foxit Reader 中打开文档,我会看到一个空白表格(在最新版本和 5.x 版本中测试过)。
我试着玩了一下,得到了这些 XfaForm(...).getDomDocument()
数据:
由 Acrobat 填充 Reader:http://pastebin.com/kXKyh9EM
由 Foxit 填充 Reader:http://pastebin.com/tiZ7EmfE
由 iText 填充:http://pastebin.com/tTKLMERC
在 iText 填充后由 Foxit Reader 填充:http://pastebin.com/Uuq0jS4b
填写的字段是 。是否有可能以与 Foxit 一起工作的方式使用 iText Reader(并且 XFA 签名保留?)
在您的 Filled by iText 示例中,有一个多余的 <xfa:data>
元素:
<xfa:datasets xmlns:xfa="http://www.xfa.org/schema/xfa-data/1.0/">
<xfa:data>
<xfa:data>
<HOZ>
<!-- rest of your data here -->
</HOZ>
</xfa:data>
</xfa:data>
<!-- data description -->
</xfa:datasets>
这是因为 XfaForm
的 fillXfaForm()
方法需要没有 <xfa:data>
的 XML 数据作为根元素。所以你的 XML 数据应该看起来像:
<HOZ>
<!-- rest of your data here -->
</HOZ>
我看到您的 readData()
方法提取现有表单数据,包括 <xfa:data>
元素:
<xfa:data>
<HOZ>
<!-- rest of your data here -->
</HOZ>
</xfa:data>
剥离外部元素应该可以解决您的问题。例如:
XfaForm xfa = new XfaForm(reader);
Node node = xfa.getDatasetsNode();
NodeList list = node.getChildNodes();
for (int i = 0; i < list.getLength(); i++) {
if ("data".equals(list.item(i).getLocalName())) {
node = list.item(i);
break;
}
}
// strip <xfa:data>
node = node.getFirstChild();
// Transformer code here