pdfbox-users mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Maruan Sahyoun <sahy...@fileaffairs.de>
Subject Re: Hybrid XFA (Livecycle) PDF - setting values of text fields in XFA
Date Mon, 12 Oct 2015 06:53:44 GMT

> Am 12.10.2015 um 00:46 schrieb Tolen Miller <tolenmiller@msn.com>:
> 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,
        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);
    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">
                        <edge presence="hidden"/>
                        <edge presence="hidden"/>
                        <edge presence="hidden"/>
               <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"/>
                  <traverse ref="header[0].txtOrderedByAddress[0]"/>
               <bind match="dataRef" ref="$.CompanyName"/>


> 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?

  • Unnamed multipart/alternative (inline, None, 0 bytes)
View raw message