使用可流布局预填充Forms
- 适用对象:
- Experience Manager 6.5
创建对象:
- 开发人员
使用可流布局预填充Forms
预先填充的表单会在呈现的表单中向用户显示数据。 例如,假设用户使用用户名和密码登录到网站。 如果验证成功,则客户端应用程序将查询数据库以获取用户信息。 数据将合并到表单中,然后表单呈现给用户。 因此,用户能够在表单中查看个性化数据。
预先填充表单具有以下优点:
- 允许用户在表单中查看自定义数据。
- 减少用户填写表单时键入内容的次数。
- 通过控制数据的放置位置来确保数据完整性。
以下两个XML数据源可以预填充表单:
- XDP数据源,它是符合XFA语法的XML(或预填充使用Acrobat创建的表单的XFDF数据)。
- 包含与表单字段名称匹配的名称/值对的任意XML数据源(本节中的示例使用任意XML数据源)。
要预填充的每个表单字段都必须存在XML元素。 XML元素名称必须与字段名称匹配。 如果XML元素与表单字段不对应,或者如果XML元素名称与字段名称不匹配,则忽略该元素。 只要指定了所有XML元素,就不必匹配XML元素的显示顺序。
在预填充已包含数据的表单时,必须指定已在XML数据源中显示的数据。 假设包含10个字段的表单在四个字段中有数据。 接下来,假设您希望预填充其余六个字段。 在这种情况下,必须在XML数据源中指定用于预填充表单的10个XML元素。 如果仅指定六个元素,则原始的四个字段为空。
例如,您可以预填充窗体,如示例确认窗体。 (请参阅呈现交互式PDF forms中的“确认表单”。)
要预填充示例确认表单,您必须创建一个XML数据源,该数据源包含与表单中的三个字段匹配的三个XML元素。 此表单包含以下三个字段:FirstName
、LastName
和Amount
。 第一步是创建一个XML数据源,该数据源包含与表单设计中的字段匹配的XML元素。 下一步是将数据值分配给XML元素,如以下XML代码中所示。
<Untitled>
<FirstName>Jerry</FirstName>
<LastName>Johnson</LastName>
<Amount>250000</Amount>
</Untitled>
使用此XML数据源预填充确认表单,然后呈现该表单后,将显示分配给XML元素的数据值,如下图所示。
使用可流动布局预填充表单
带可流动布局的Forms可用于向用户显示未确定的数据量。 由于表单的布局会自动根据合并的数据量进行调整,因此您无需像处理具有固定布局的表单那样预先确定表单的固定布局或页数。
通常,表单会填充在运行时获取的数据。 因此,您可以通过创建内存中XML数据源并将数据直接放入内存中XML数据源来预填充表单。
考虑一个基于Web的应用程序,如在线商店。 在线购物者完成购买项目后,所有购买的项目都会放入内存中的XML数据源,该数据源用于预填充表单。 下图显示了此流程,图后的表中对此进行了说明。
下表描述了此图中的步骤。
下图显示了采购订单表单的示例。 表中的信息可以根据XML数据中的记录数进行调整。
窗体设计注意事项
带可流动布局的Forms基于在Designer中创建的表单设计。 表单设计指定一组布局、呈现和数据捕获规则,包括基于用户输入计算值。 数据输入到表单中时将应用规则。 添加到表单的字段是表单设计内的子表单。 例如,在上图所示的采购订单表单中,每行都是一个子表单。 有关创建包含子表单的表单设计的信息,请参阅创建具有可流动布局的采购订单表单。
了解数据子组
XML数据源用于预先填充具有固定布局和可流动布局的表单。 但是,不同之处在于,使用可流动布局预填充表单的XML数据源包含用于预填充表单内重复的子表单的重复XML元素。 这些重复的XML元素称为数据子组。
用于预填充上图所示的采购订单表单的XML数据源包含四个重复的数据子组。 每个数据子组对应于购买的项目。 所购物品包括显示器、台灯、电话和通讯录。
以下XML数据源用于预填充采购订单表单。
<header>
<!-- XML elements used to prepopulate non-repeating fields such as address
<!and city
<txtPONum>8745236985</txtPONum>
<dtmDate>2004-02-08</dtmDate>
<txtOrderedByCompanyName>Any Company Name</txtOrderedByCompanyName>
<txtOrderedByAddress>555, Any Blvd.</txtOrderedByAddress>
<txtOrderedByCity>Any City</txtOrderedByCity>
<txtOrderedByStateProv>ST</txtOrderedByStateProv>
<txtOrderedByZipCode>12345</txtOrderedByZipCode>
<txtOrderedByCountry>Any Country</txtOrderedByCountry>
<txtOrderedByPhone>(123) 456-7890</txtOrderedByPhone>
<txtOrderedByFax>(123) 456-7899</txtOrderedByFax>
<txtOrderedByContactName>Contact Name</txtOrderedByContactName>
<txtDeliverToCompanyName>Any Company Name</txtDeliverToCompanyName>
<txtDeliverToAddress>7895, Any Street</txtDeliverToAddress>
<txtDeliverToCity>Any City</txtDeliverToCity>
<txtDeliverToStateProv>ST</txtDeliverToStateProv>
<txtDeliverToZipCode>12346</txtDeliverToZipCode>
<txtDeliverToCountry>Any Country</txtDeliverToCountry>
<txtDeliverToPhone>(123) 456-7891</txtDeliverToPhone>
<txtDeliverToFax>(123) 456-7899</txtDeliverToFax>
<txtDeliverToContactName>Contact Name</txtDeliverToContactName>
</header>
<detail>
<!-- A data subgroup that contains information about the monitor>
<txtPartNum>00010-100</txtPartNum>
<txtDescription>Monitor</txtDescription>
<numQty>1</numQty>
<numUnitPrice>350.00</numUnitPrice>
</detail>
<detail>
<!-- A data subgroup that contains information about the desk lamp>
<txtPartNum>00010-200</txtPartNum>
<txtDescription>Desk lamps</txtDescription>
<numQty>3</numQty>
<numUnitPrice>55.00</numUnitPrice>
</detail>
<detail>
<!-- A data subgroup that contains information about the Phone>
<txtPartNum>00025-275</txtPartNum>
<txtDescription>Phone</txtDescription>
<numQty>5</numQty>
<numUnitPrice>85.00</numUnitPrice>
</detail>
<detail>
<!-- A data subgroup that contains information about the address book>
<txtPartNum>00300-896</txtPartNum>
<txtDescription>Address book</txtDescription>
<numQty>2</numQty>
<numUnitPrice>15.00</numUnitPrice>
</detail>
请注意,每个数据子组都包含对应于此信息的四个XML元素:
- 项目部件号
- 物料说明
- 物料数量
- 单价
数据子组的父XML元素的名称必须与窗体设计中的子窗体的名称匹配。 例如,在上一个图中,请注意数据子组的父XML元素的名称为detail
。 这与采购订单表单所基于的表单设计中子表单的名称相对应。 如果数据子组的父XML元素的名称与子表单不匹配,则不会预填充服务器端表单。
每个数据子组都必须包含与子表单中的字段名称匹配的XML元素。 窗体设计中的detail
子窗体包含以下字段:
- txtPartNum
- txtDescription
- numQty
- numUnitPrice
RenderAtClient
选项设置为No
,则只有第一个数据记录会合并到表单中。 为确保所有数据记录都合并到表单中,请将RenderAtClient
设置为Yes
。 有关RenderAtClient
选项的信息,请参阅在客户端渲染Forms。步骤摘要
要使用可流式布局预填充表单,请执行以下任务:
- 包括项目文件。
- 创建内存中XML数据源。
- 转换XML数据源。
- 呈现预填充的表单。
包含项目文件
在开发项目中包含必要的文件。 如果要使用Java创建客户端应用程序,请包含必要的JAR文件。 如果使用Web服务,请确保包含代理文件。
包含项目文件
在开发项目中包含必要的文件。 如果要使用Java创建客户端应用程序,请包含必要的JAR文件。 如果使用Web服务,请确保包含代理文件。
创建内存中的XML数据源
可以使用org.w3c.dom
类创建内存中的XML数据源,以预填充具有可流动布局的表单。 将数据放置到符合表单的XML数据源中。 有关具有可流动布局的表单与XML数据源之间的关系的信息,请参阅了解数据子组。
转换XML数据源
使用org.w3c.dom
类创建的内存中XML数据源可以转换为com.adobe.idp.Document
对象,然后才可用于预填充表单。 内存中的XML数据源可以使用Java XML转换类进行转换。
org.w3c.dom.Document
对象转换为BLOB
对象。呈现预填充的表单
您可以像呈现其他表单一样呈现预填充的表单。 唯一的区别是,您使用包含XML数据源的com.adobe.idp.Document
对象来预填充表单。
另请参阅
使用Java API预填充表单
要使用Forms API (Java)预填充具有可流动布局的表单,请执行以下步骤:
-
包含项目文件
在Java项目的类路径中包含客户端JAR文件,例如adobe-forms-client.jar。 有关这些文件的位置的信息,请参阅包括AEM Forms Java库文件。
-
创建内存中XML数据源
-
通过调用
DocumentBuilderFactory
类newInstance
方法创建JavaDocumentBuilderFactory
对象。 -
通过调用
DocumentBuilderFactory
对象的newDocumentBuilder
方法创建JavaDocumentBuilder
对象。 -
调用
DocumentBuilder
对象的newDocument
方法以实例化org.w3c.dom.Document
对象。 -
通过调用
org.w3c.dom.Document
对象的createElement
方法创建XML数据源的根元素。 这将创建一个表示根元素的Element
对象。 将表示元素名称的字符串值传递给createElement
方法。 将返回值强制转换为Element
。 接下来,通过调用Document
对象的appendChild
方法将根元素附加到文档,并将根元素对象作为参数传递。 以下代码行显示了此应用程序逻辑:Element root = (Element)document.createElement("transaction"); document.appendChild(root);
-
通过调用
Document
对象的createElement
方法创建XML数据源的标头元素。 将表示元素名称的字符串值传递给createElement
方法。 将返回值强制转换为Element
。 接下来,通过调用root
对象的appendChild
方法,将标头元素附加到根元素,并将标头元素对象作为参数传递。 附加到标题元素的XML元素对应于表单的静态部分。 以下代码行显示此应用程序逻辑:Element header = (Element)document.createElement("header"); root.appendChild(header);
-
通过调用
Document
对象的createElement
方法,创建属于标头元素的子元素,并传递表示该元素名称的字符串值。 将返回值强制转换为Element
。 接下来,通过调用子元素的appendChild
方法为其设置值,并将Document
对象的createTextNode
方法作为参数传递。 指定作为子元素的值显示的字符串值。 最后,通过调用标头元素的appendChild
方法将子元素附加到标头元素,并将子元素对象作为参数传递。 以下代码行显示此应用程序逻辑:Element poNum= (Element)document.createElement("txtPONum"); poNum.appendChild(document.createTextNode("8745236985")); header.appendChild(LastName);
-
通过重复表单静态部分中出现的每个字段的上一个子步骤,将所有剩余的元素添加到标题元素中(在XML数据源图表中,这些字段显示在A部分中。(请参阅了解数据子组)
-
通过调用
Document
对象的createElement
方法创建XML数据源的详细信息元素。 将表示元素名称的字符串值传递给createElement
方法。 将返回值强制转换为Element
。 接下来,通过调用root
对象的appendChild
方法,将detail元素附加到根元素,并将该detail元素对象作为参数传递。 附加到详细信息元素的XML元素对应于表单的动态部分。 以下代码行显示此应用程序逻辑:Element detail = (Element)document.createElement("detail"); root.appendChild(detail);
-
通过调用
Document
对象的createElement
方法,创建属于该详细信息元素的子元素,并传递表示该元素名称的字符串值。 将返回值强制转换为Element
。 接下来,通过调用子元素的appendChild
方法为其设置值,并将Document
对象的createTextNode
方法作为参数传递。 指定作为子元素的值显示的字符串值。 最后,通过调用detail元素的appendChild
方法,将子元素附加到detail元素,并将子元素对象作为参数传递。 以下代码行显示此应用程序逻辑:Element txtPartNum = (Element)document.createElement("txtPartNum"); txtPartNum.appendChild(document.createTextNode("00010-100")); detail.appendChild(txtPartNum);
-
对所有XML元素重复最后一个子步骤以附加到详细信息元素。 要正确创建用于填充采购订单表单的XML数据源,必须将以下XML元素附加到详细信息元素:
txtDescription
、numQty
和numUnitPrice
。 -
对用于预填充表单的所有数据项重复前两个子步骤。
-
-
转换XML数据源
- 通过调用
javax.xml.transform.Transformer
对象的静态newInstance
方法创建javax.xml.transform.Transformer
对象。 - 通过调用
TransformerFactory
对象的newTransformer
方法创建Transformer
对象。 - 使用构造函数创建
ByteArrayOutputStream
对象。 - 使用对象的构造函数创建
javax.xml.transform.dom.DOMSource
对象,并传递在步骤1中创建的org.w3c.dom.Document
对象。 - 使用对象的构造函数创建
javax.xml.transform.dom.DOMSource
对象并传递ByteArrayOutputStream
对象。 - 通过调用
javax.xml.transform.Transformer
对象的transform
方法并传递javax.xml.transform.dom.DOMSource
和javax.xml.transform.stream.StreamResult
对象来填充JavaByteArrayOutputStream
对象。 - 创建字节数组并将
ByteArrayOutputStream
对象的大小分配给字节数组。 - 通过调用
ByteArrayOutputStream
对象的toByteArray
方法填充字节数组。 - 使用对象的构造函数并传递字节数组来创建一个
com.adobe.idp.Document
对象。
- 通过调用
-
呈现预填充的表单
调用
FormsServiceClient
对象的renderPDFForm
方法并传递以下值:- 一个字符串值,它指定窗体设计名称,包括文件扩展名。
- 包含要与表单合并的数据的
com.adobe.idp.Document
对象。 确保使用在步骤1和步骤2中创建的com.adobe.idp.Document
对象。 - 存储运行时选项的
PDFFormRenderSpec
对象。 - 包含Forms服务所需URI值的
URLSpec
对象。 - 存储文件附件的
java.util.HashMap
对象。 这是一个可选参数,如果您不想将文件附加到表单,则可以指定null
。
renderPDFForm
方法返回的FormsResult
对象包含必须写入客户端Web浏览器的表单数据流。- 创建用于将表单数据流发送到客户端Web浏览器的
javax.servlet.ServletOutputStream
对象。 - 通过调用
FormsResult
对象的getOutputContent
方法创建com.adobe.idp.Document
对象。 - 通过调用
com.adobe.idp.Document
对象的getInputStream
方法创建java.io.InputStream
对象。 - 通过调用
InputStream
对象的read
方法并将该字节数组作为参数传递,创建字节数组以表单数据流填充该字节数组。 - 调用
javax.servlet.ServletOutputStream
对象的write
方法将表单数据流发送到客户端Web浏览器。 将字节数组传递给write
方法。
使用Web服务API预填充表单
要使用Forms API(Web服务)预填充具有可流动布局的表单,请执行以下步骤:
-
包含项目文件
- 创建使用Forms服务WSDL的Java代理类。 (请参阅使用Apache Axis创建Java代理类。)
- 将Java代理类包含在类路径中。
-
创建内存中XML数据源
-
通过调用
DocumentBuilderFactory
类newInstance
方法创建JavaDocumentBuilderFactory
对象。 -
通过调用
DocumentBuilderFactory
对象的newDocumentBuilder
方法创建JavaDocumentBuilder
对象。 -
调用
DocumentBuilder
对象的newDocument
方法以实例化org.w3c.dom.Document
对象。 -
通过调用
org.w3c.dom.Document
对象的createElement
方法创建XML数据源的根元素。 这将创建一个表示根元素的Element
对象。 将表示元素名称的字符串值传递给createElement
方法。 将返回值强制转换为Element
。 接下来,通过调用Document
对象的appendChild
方法将根元素附加到文档,并将根元素对象作为参数传递。 以下代码行显示此应用程序逻辑:Element root = (Element)document.createElement("transaction"); document.appendChild(root);
-
通过调用
Document
对象的createElement
方法创建XML数据源的标头元素。 将表示元素名称的字符串值传递给createElement
方法。 将返回值强制转换为Element
。 接下来,通过调用root
对象的appendChild
方法,将标头元素附加到根元素,并将标头元素对象作为参数传递。 附加到标题元素的XML元素对应于表单的静态部分。 以下代码行显示此应用程序逻辑:Element header = (Element)document.createElement("header"); root.appendChild(header);
-
通过调用
Document
对象的createElement
方法,创建属于标头元素的子元素,并传递表示该元素名称的字符串值。 将返回值强制转换为Element
。 接下来,通过调用子元素的appendChild
方法为其设置值,并将Document
对象的createTextNode
方法作为参数传递。 指定作为子元素的值显示的字符串值。 最后,通过调用标头元素的appendChild
方法将子元素附加到标头元素,并将子元素对象作为参数传递。 以下代码行显示了此应用程序逻辑:Element poNum= (Element)document.createElement("txtPONum"); poNum.appendChild(document.createTextNode("8745236985")); header.appendChild(LastName);
-
通过重复表单静态部分中出现的每个字段的上一个子步骤,将所有剩余的元素添加到标题元素中(在XML数据源图表中,这些字段显示在A部分中。(请参阅了解数据子组)
-
通过调用
Document
对象的createElement
方法创建XML数据源的详细信息元素。 将表示元素名称的字符串值传递给createElement
方法。 将返回值强制转换为Element
。 接下来,通过调用root
对象的appendChild
方法,将detail元素附加到根元素,并将该detail元素对象作为参数传递。 附加到详细信息元素的XML元素对应于表单的动态部分。 以下代码行显示了此应用程序逻辑:Element detail = (Element)document.createElement("detail"); root.appendChild(detail);
-
通过调用
Document
对象的createElement
方法,创建属于该详细信息元素的子元素,并传递表示该元素名称的字符串值。 将返回值强制转换为Element
。 接下来,通过调用子元素的appendChild
方法为其设置值,并将Document
对象的createTextNode
方法作为参数传递。 指定作为子元素的值显示的字符串值。 最后,通过调用detail元素的appendChild
方法,将子元素附加到detail元素,并将子元素对象作为参数传递。 以下代码行显示了此应用程序逻辑:Element txtPartNum = (Element)document.createElement("txtPartNum"); txtPartNum.appendChild(document.createTextNode("00010-100")); detail.appendChild(txtPartNum);
-
对所有XML元素重复最后一个子步骤以附加到详细信息元素。 要正确创建用于填充采购订单表单的XML数据源,必须将以下XML元素附加到详细信息元素:
txtDescription
、numQty
和numUnitPrice
。 -
对用于预填充表单的所有数据项重复前两个子步骤。
-
-
转换XML数据源
- 通过调用
javax.xml.transform.Transformer
对象的静态newInstance
方法创建javax.xml.transform.Transformer
对象。 - 通过调用
TransformerFactory
对象的newTransformer
方法创建Transformer
对象。 - 使用构造函数创建
ByteArrayOutputStream
对象。 - 使用对象的构造函数创建
javax.xml.transform.dom.DOMSource
对象,并传递在步骤1中创建的org.w3c.dom.Document
对象。 - 使用对象的构造函数创建
javax.xml.transform.dom.DOMSource
对象并传递ByteArrayOutputStream
对象。 - 通过调用
javax.xml.transform.Transformer
对象的transform
方法并传递javax.xml.transform.dom.DOMSource
和javax.xml.transform.stream.StreamResult
对象来填充JavaByteArrayOutputStream
对象。 - 创建字节数组并将
ByteArrayOutputStream
对象的大小分配给字节数组。 - 通过调用
ByteArrayOutputStream
对象的toByteArray
方法填充字节数组。 - 使用构造函数创建
BLOB
对象并调用其setBinaryData
方法并传递字节数组。
- 通过调用
-
呈现预填充的表单
调用
FormsService
对象的renderPDFForm
方法并传递以下值:- 一个字符串值,它指定窗体设计名称,包括文件扩展名。
- 包含要与表单合并的数据的
BLOB
对象。 确保您使用在步骤1和步骤2中创建的BLOB
对象。 - 存储运行时选项的
PDFFormRenderSpecc
对象。 有关详细信息,请参阅AEM Forms API引用。 - 包含Forms服务所需URI值的
URLSpec
对象。 - 存储文件附件的
java.util.HashMap
对象。 这是一个可选参数,如果您不想将文件附加到表单,则可以指定null
。 - 方法填充的空
com.adobe.idp.services.holders.BLOBHolder
对象。 用于存储渲染的PDF表单。 - 方法填充的空
javax.xml.rpc.holders.LongHolder
对象。 (此参数将存储表单中的页数)。 - 方法填充的空
javax.xml.rpc.holders.StringHolder
对象。 (此参数将存储区域设置值)。 - 将包含此操作结果的空
com.adobe.idp.services.holders.FormsResultHolder
对象。
renderPDFForm
方法使用必须写入客户端Web浏览器的表单数据流填充作为最后一个参数值传递的com.adobe.idp.services.holders.FormsResultHolder
对象。- 通过获取
com.adobe.idp.services.holders.FormsResultHolder
对象的value
数据成员的值创建FormResult
对象。 - 通过调用
FormsResult
对象的getOutputContent
方法,创建包含表单数据的BLOB
对象。 - 通过调用其
getContentType
方法获取BLOB
对象的内容类型。 - 通过调用其
setContentType
方法并传递BLOB
对象的内容类型来设置javax.servlet.http.HttpServletResponse
对象的内容类型。 - 通过调用
javax.servlet.http.HttpServletResponse
对象的getOutputStream
方法,创建用于将表单数据流写入客户端Web浏览器的javax.servlet.ServletOutputStream
对象。 - 创建字节数组,并通过调用
BLOB
对象的getBinaryData
方法填充该数组。 此任务将FormsResult
对象的内容分配给字节数组。 - 调用
javax.servlet.http.HttpServletResponse
对象的write
方法将表单数据流发送到客户端Web浏览器。 将字节数组传递给write
方法。
NOTE
renderPDFForm
方法使用必须写入客户端Web浏览器的表单数据流填充作为最后一个参数值传递的com.adobe.idp.services.holders.FormsResultHolder
对象。