Hi,
> Am 12.10.2015 um 00:46 schrieb Tolen Miller <[email protected]>:
>
> I'm using version 1.8.10 and had some great help in a previous thread
> (subject: Cannot load pre existing PDF to access fields). I have been able
> to successfully load a pre existing fill-able PDF (created in LiveCycle);
> get a map of text fields from the getFieldNameList() method; then use a
> comparison of the field name on the pdf and name of the database field to
> map values onto the pdf.
>
> In the end of that thread, I mentioned my own trouble with also filling the
> XFA portion of the form. In the end, I opted to rip out the XFA (acroForm.
> setXFA(null);) in order to get the filled static PDF to display in Adobe's
> products. I have been working on another project in the past few weeks, but
> am again looking at filling the XFA. After looking at the PDXFA, I am
> having trouble getting a similar map or list of text field names from the
> XFA. This was my first attempt, but I'm not getting what I was expecting:
would it be possible to upload a sample form to a public location to take a
closer look?
>
> System.out.println("Setting up XFA");
> PDXFA xfa = acroForm.getXFA();
> Document xmlDoc = xfa.getDocument();
> NodeList dataElements = xmlDoc.getElementsByTagName("xfa:data");
> HashMap<String, Integer> xmlFields = new HashMap<String, Integer>();
> if (dataElements != null) {
> for (int i = 0; i < dataElements.getLength(); i++) {
> xmlFields.put(dataElements.item(0).getNodeName(), i);
> }
> }
>
your need to recurse down into the nodes below xfa:data. Something like
public static void main(String[] args) throws IOException,
ParserConfigurationException, SAXException
{
PDDocument document = PDDocument.loadNonSeq(...);
PDXFA xfa = document.getDocumentCatalog().getAcroForm().getXFA();
Document xmlDoc = xfa.getDocument();
Node xfaData = xmlDoc.getElementsByTagName("xfa:data").item(0);
HashMap<String, String> xmlFields = new HashMap<String, String>();
getDataElements(xfaData, xmlFields);
System.out.println(xmlFields);
}
public static void getDataElements(Node node, HashMap<String, String>
xmlFields) {
NodeList nodeList = node.getChildNodes();
for (int i = 0; i < nodeList.getLength(); i++) {
Node currentNode = nodeList.item(i);
if (currentNode.getNodeType() == Node.ELEMENT_NODE &&
currentNode.hasChildNodes()) {
//calls this method for all the children which is Element
getDataElements(currentNode, xmlFields);
} else {
xmlFields.put(currentNode.getNodeName(),
currentNode.getNodeValue());
}
}
}
It could also be that xfa:data is empty or doesn't have all fields e.g. for
dynamic forms. To get the fields as designed you need to look into the template
node and look for subform and field nodes. Things can get a little more
complicated as there is a <traversal> and there might be a <bind> elements
which tell you a little more about the structure of the form and the data
binding of an element. <bind> is there if the data binding for the field is not
done by matching the field name. A small snippet below
<field h="6.35mm" name="txtOrderedByCompanyName" w="82.55mm"
y="52.07mm">
<ui>
<textEdit>
<border>
<edge presence="hidden"/>
<edge presence="hidden"/>
<edge/>
<edge presence="hidden"/>
</border>
<margin/>
</textEdit>
</ui>
<font size="9pt" typeface="Myriad Pro"/>
<margin bottomInset="0mm" leftInset="0mm" rightInset="0mm"
topInset="0mm"/>
<para marginLeft="0pt" vAlign="middle"/>
<caption reserve="15.24mm">
<para vAlign="middle"/>
<value>
<text>Company</text>
</value>
</caption>
<traversal>
<traverse ref="header[0].txtOrderedByAddress[0]"/>
</traversal>
<bind match="dataRef" ref="$.CompanyName"/>
</field>
BR
Maruan
> My hope, after that code snippet, was to match on the String of the
> xmlFields map with a field name from my db, then use the int as the
> position of the dataElements list to set the text value (which would show
> as the filled value in the pdf). Where have I gone wrong?