A form, in InfoPath terms, is an XML document that is associated with a particular form template and that conforms to the XML schema defined by that form template, though as we'll see in our first example solution, the use of a schema is not required. Such files are created every time a user fills out a new form using an existing form template. A form template, or solution, consists of a set of XML, XSLT, XSD, and optional script files that work together to define everything about how the form looks and behaves, how it binds to the underlying XML document's elements and attributes, and how the data is validated. A form template occurs as one of the following:
To fill out a new form, a user simply opens an existing form template (.xsn or .xsf file). The form template might reside on the user's own computer, but more often it is retrieved from a central location such as a web server. This allows multiple people to use the same form template. InfoPath then launches the form in its initial empty state. To make changes to a form that has already been filled out, a user would open the existing XML file, make changes, and save those changes, either locally on his or her own computer for later editing, or remotely via a submission mechanism defined in the form template. Saved forms can even be emailed to other InfoPath users for subsequent editing.
One of the best ways to learn how InfoPath solutions work is to examine and experiment with the sample forms that come bundled with the application. First select File Design a Form... Customize a Sample. Then choose one of the many sample forms that can be customized. To view the individual form template files for that solution, or for any other .xsn file in design mode, select File Extract Form Files... All of the files will be output into the directory that you choose.
10.3.1 The InfoPath Processing Instructions
XML documents edited by InfoPath retain their association with the InfoPath application in general and with a specific solution in particular through the use of special processing instructions (PI) inserted into the prolog of the instance document. All XML files created by or edited using InfoPath automatically include these PIs. To manually associate an XML document with the InfoPath application, use the now familiar mso-application PI:
<?mso-application prog?> <doc>...</doc>
This will associate the file with the InfoPath application. Windows Explorer will render the file using the InfoPath icon and will launch InfoPath when a user opens the file. But if you only include an mso-application PI, InfoPath will display an error message when trying to open the file. To avoid this, you'll also need to associate the document with a particular solution, by using the mso-infoPathSolution PI. Example 10-1 shows a complete XML document whose PIs associate it with both the InfoPath application and a particular InfoPath solution.
Example 10-1. An InfoPath "form," myAnnouncement.xml
<?mso-application prog?> <?mso-infoPathSolution href="manifest.xsf" PIVersion="188.8.131.52"?> <announcement> <headline>Building closes early</headline> <body>The building will be closing an hour early today, at 9pm.</body> </announcement>
The href pseudo-attribute in Example 10-1 points to the location of a form definition file (*.xsf) or form template package (*.xsn). The PIVersion pseudo-attribute is required. The current version of the PI is 184.108.40.206; future versions may introduce new features or be interpreted differently.
There are also two optional pseudo-attributes not shown here. The solutionVersion pseudo-attribute can be used to identify the version of the solution that was last used to edit the file. This is useful in the context of managing solution upgrades. And the productVersion pseudo-attribute is used to identify the version of the InfoPath application that was used to edit this file. Both of these pseudo-attributes are automatically included in the solution PI when InfoPath saves a filled-out form.
10.3.2 A Simple Form Definition File
The form definition file, or "solution manifest," is the starting point for defining an InfoPath solution by hand. Example 10-2 shows a simple form definition file that includes only the bare minimum of what's required to define a form template. No optional features are utilized.
Example 10-2. A minimal form definition file, manifest.xsf
<xsf:xDocumentClass solutionFormatVersion="220.127.116.11" xmlns:xsf= "http://schemas.microsoft.com/office/infopath/2003/solutionDefinition"> <xsf:views> <xsf:view name="Announcement Form"> <xsf:mainpane transform="announcement.xsl"/> </xsf:view> </xsf:views> <xsf:package> <xsf:files> <xsf:file name="announcement.xsl"/> </xsf:files> </xsf:package> </xsf:xDocumentClass>
From this minimal example, we see that the root element, xsf:xDocumentClass, has a required attribute, solutionFormatVersion, and two required element children, xsf:views and xsf:package (whose relative order is insignificant). The attribute indicates the version of the form definition file format we're using; in this case, it's 18.104.22.168. The xsf:views element must contain at least one xsf:view element. Each view in turn must have one xsf:mainpane element that refers to an XSLT stylesheet in its transform attribute. The stylesheet referred to here is what transforms the source XML document into the form's HTML-based editing view. The xsf:package element contains a reference to each of the files used in the solution. This example declares only one file, the required XSLT stylesheet.
Filenames referred to by xsf:file elements must all be pathnames that are relative to the location of the form definition file itself. This will ensure that they are resolved correctly whether InfoPath opens the solution via the form definition file (*.xsf) or via a form template package (*.xsn).
All internal references to subordinate files, such as included or imported stylesheet modules or schema files, must be relative and must also be declared in the form definition file using corresponding xsf:file elements.
10.3.3 Defining a Form Using Only an XSLT Stylesheet
The minimal form definition file we saw in Example 10-2 declares only one additional file, the XSLT stylesheet. To a limited extent, the stylesheet on its own is sufficient to define a round-trip mapping between a source document and an editing view. Even a schema is not necessary. This is how it works: the XSLT stylesheet is interpreted in such a way that implicit bindings are automatically created between HTML nodes in the editing view and XML nodes in the source document. We will explore two types of implicit bindings in this chapter:
Our current solution example will illustrate text bindings. Our second solution example, which we'll see later in "A More Complete Example," will additionally illustrate structural bindings.
Text bindings are established in the following manner: any instances of the xsl:value-of instruction in the stylesheet will automatically be rendered as editable text boxes in the resulting InfoPath form, provided that the following two conditions hold:
If one of these conditions does not apply, then the value will still be displayed as instructed by the stylesheet, but the field will not be editable. In the event that both conditions apply but you nevertheless don't want the field to be editable, you can disable this behavior by annotating the XSLT instruction as follows:
<span ... > <xsl:value-of select="expression " xd:disableEditing="yes" /> </span>
The presence of xd:disableEditing="yes" will keep InfoPath from automatically establishing the text binding and making the field editable. The xd prefix (recalling InfoPath's pre-release code name, "XDocs") in the above and subsequent examples must map to the InfoPath namespace URI:
Example 10-3 shows an XSLT stylesheet that transforms an XML document into a simple HTML view, displaying the values of two elements in the source document and establishing implicit text bindings for them.
Example 10-3. An XSLT-defined editing view, announcement.xsl
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="/announcement"> <html> <head> <title>Announcement</title> </head> <body> <h1> <xsl:value-of select="headline"/> </h1> <p> <xsl:value-of select="body"/> </p> </body> </html> </xsl:template> </xsl:stylesheet>
We now have three files:
Provided that these three files are in the same directory, double-clicking the myAnnouncement.xml file will cause InfoPath to launch in editing mode and display the document using the editing view defined by announcement.xsl. The resulting view is shown in Figure 10-2.
Figure 10-2. Opening a filled-out form, myAnnouncement.xml
Note that the headline field is highlighted with a box around it. This is what an editable text box looks like when instantiated as an HTML h1 element. The end user can make edits as necessary and then simply tab or click into the body field to make changes there as well. The HTML h1 and p element nodes are said to be bound to the XML headline and body nodes, respectively. Every time the user registers a change, that change is propagated to the underlying XML, and the XSLT stylesheet is immediately reapplied. The change is registered when the user takes the focus off the field that was changed (usually by tabbing to the next field).
The automatic bindings via the xsl:value-of instructions work in our example, because both of the two previously mentioned conditions are satisfied as follows:
InfoPath's use of text bindings to create editable fields allows virtually any HTML element that can contain text to function as a text box. Thus, text boxes are created using text bindings, rather than using the HTML input element, as might otherwise have been expected.
This mechanism is certainly a convenient way to get started, but editing requirements tend to be more complex than what this feature supports. For all but the simplest document types, more will be needed.
10.3.3.1 Conditional formatting
Before moving on to further ways of binding HTML nodes in the view to XML nodes in the source, let's take a detour down the strange and wonderful road of conditional formatting. Conditional formatting describes the ability to alter some aspect of the editing view according to some condition in the XML source document. It's a commonly expected feature of forms-based XML editors.
A consequence of InfoPath's processing model, in which the XSLT stylesheet is reapplied every time the user registers a change, is that you can specify conditional formatting rules directly in XSLT. This is useful, for example, for rendering derived number values in black type but changing them to red when they become negative. Usefulness aside, you can get an idea of the potential this construct has by taking a look at Example 10-4. This stylesheet is the same as our original announcements.xsl stylesheet, except for the addition of a conditional statement.
Example 10-4. Conditional formatting expressed in XSLT
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="/announcement"> <html> <head> <title>Announcement</title> </head> <body> <xsl:choose> <xsl:when test="starts-with(headline,'SpEcIaL CoDe')"> <div style="font-family: Arial;"> <xsl:value-of select="headline"/> </div> <div style="font-family: Comic Sans MS;"> <xsl:value-of select="headline"/> </div> <div style="font-family: Wingdings;"> <xsl:value-of select="headline"/> </div> <p style="font-size: 50px;"> CONGRATS! YOU UNLOCKED THE SPECIAL CODE!! </p> </xsl:when> <xsl:otherwise> <h1> <xsl:value-of select="headline"/> </h1> </xsl:otherwise> </xsl:choose> <p> <xsl:value-of select="body"/> </p> </body> </html> </xsl:template> </xsl:stylesheet>
Our solution will continue to behave exactly as it did before, until some unsuspecting user enters a value in the headline field that starts exactly with the string SpEcIaL CoDe. At the moment the user takes the focus off the field (by tabbing to the next one), they'll get the surprise shown in Figure 10-3. The change is registered, the text content of the headline element is updated, the XSLT is reapplied, and, with great satisfaction, our condition succeeds.
Figure 10-3. Fun with conditional formatting
Regardless of the presence of a conditional statement, this example also demonstrates another possibility: multiple HTML nodes in the view being bound to the same XML node in the source. In this view we have a total of four text boxes even though they are bound to a total of only two XML nodes. As you would expect, when the user registers a change to one of the three "SpEcIaL CoDe" fields, the other fields are updated accordingly or they disappear altogether if the field's value no longer starts with our very special code.
Keep in mind that an HTML node in the view does not have to be bound to an XML node in the source for it to display its value, or some derivative thereof. As it happens, each of the HTML nodes in our example creates an implicit binding to the underlying XML node, resulting in the proliferation of text boxes. But if one of the xsl:value-of instructions had xd:disableEditing="yes", or if one of the two necessary conditions on it did not apply, then the binding would not occur and no text box would result. The value, however, would still display as instructed by the stylesheet. Another way to disable the automatic text binding is to wrap the select expression in the XPath string( ) function. In that case, the same result is displayed, but the binding is disabled, because the expression evaluates to a string rather than to a node-set.
One final thing to note about Figure 10-3 is the presence of the squiggly lines under each instance of "SpEcIaL CoDeS", even the Wingdings rendition. This is the InfoPath spelling checker in action. The spelling checker and AutoComplete features are turned on by default for HTML nodes that are implicitly bound to XML source nodes. To override this behavior, you need to declare and parameterize the corresponding xField control in the form definition file. See Section 10.4.4.6 later in this chapter.
10.3.4 Explicitly Binding HTML Nodes to XML Nodes
We've now seen a mechanism by which HTML nodes in the view are implicitly bound to XML nodes in the source document being edited. You can also explicitly specify bindings in the HTML view by annotating the XSLT stylesheet with attributes in the InfoPath namespace. The most important of these attributes is xd:binding. (We'll see an example that uses the xd:binding attribute later in this chapter, under "Date picker control.") By attaching this attribute to an HTML element in the XSLT stylesheet, you are telling InfoPath to bind that element to a particular node in the XML source tree. The value of the xd:binding attribute is an XPath expression that is evaluated in the current XSLT context. It selects the element or attribute node to which this HTML element will be bound. This explicit binding takes precedence over any implicit binding that would otherwise occur.
The other primary annotation that InfoPath uses is the xd:xctname attribute, which identifies the type of control that a particular HTML element functions. While, under certain circumstances, the InfoPath editor will not work correctly if the xd:xctname attribute is not present (e.g., the date picker control requires its presence), it is primarily needed only by InfoPath design mode rather than editing mode. Except for the specific controls that require it, you can generally avoid this attribute when creating solutions by hand. That means you don't need to know the xd:xctname attribute's possible values, shown here:
Again, since you generally don't need to worry about the xd:xctname attribute, this list is not directly useful except to illustrate what kinds of controls InfoPath supports. The items in this list correspond to available controls in InfoPath design mode's Controls task pane (shown later in this chapter, in Figure 10-11).
10.3.5 Specifying an Initial XML Template
When a user opens an XML file that is already associated with an InfoPath solution via the InfoPath PIs, InfoPath launches the file with the form view defined by that solution. However, when a user directly opens a form definition file (*.xsf) or package (*.xsn) in order to fill out a new form, InfoPath needs an "empty" XML template, or skeleton, from which to begin. This initial XML template is specified in the form definition file, using the xsf:initialXmlDocument element child of the xsf:fileNew element. Example 10-5 shows our minimal form definition file with the additional specification of an initial XML template. Note that, as is the case with all of a solution's files, the initial XML template must also be declared in the list of files within the xsf:package element.
Example 10-5. Specifying the initial XML document
<xsf:xDocumentClass solutionFormatVersion="22.214.171.124" xmlns:xsf="http://schemas.microsoft.com/office/infopath/2003/solutionDefinition"> <xsf:views> <xsf:view name="Announcement Form"> <xsf:mainpane transform="announcement.xsl"/> </xsf:view> </xsf:views> <xsf:package> <xsf:files> <xsf:file name="announcement.xsl"/> <xsf:file name="template.xml"/> </xsf:files> </xsf:package> <xsf:fileNew> <xsf:initialXmlDocument caption="Announcement" href="template.xml"/> </xsf:fileNew> </xsf:xDocumentClass>
The initial XML template file normally consists mostly of empty elements and attributes but can also include default values, such as an initial value of 0 for a decimal-valued field. Example 10-6 shows an example initial XML template. Note that the mso-infoPathSolution PI must be included and must refer to the relative path of the form definition file.
Example 10-6. An example initial XML template, template.xml
<?mso-infoPathSolution href="manifest.xsf" PIVersion="126.96.36.199"?> <?mso-application prog?> <announcement> <headline></headline> <body></body> </announcement>
10.3.6 Adding a Schema
While using a schema is not required, it buys you a lot in terms of automatic data validation. Fields that should be dates, for example, will be flagged as invalid if anything other than a valid date is entered into it. Example 10-7 shows a schema that we could add to our example solution.
Example 10-7. A simple XSD schema, announcement.xsd
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" elementFormDefault="unqualified"> <xsd:element name="announcement"> <xsd:complexType> <xsd:sequence> <xsd:element name="headline"> <xsd:simpleType> <xsd:restriction base="xsd:string"> <xsd:maxLength value="40"/> </xsd:restriction> </xsd:simpleType> </xsd:element> <xsd:element name="body" type="xsd:string"/> </xsd:sequence> </xsd:complexType> </xsd:element> </xsd:schema>
This schema requires that the headline element's value not exceed 40 characters in length. To see what effect this will have on our solution, we first need to add it to the solution. Example 10-8 shows the final version of our minimal form definition file, with the schema declared using the xsf:documentSchema element.
Example 10-8. Declaring a schema in the form definition file
<xsf:xDocumentClass solutionFormatVersion="188.8.131.52" xmlns:xsf="http://schemas.microsoft.com/office/infopath/2003/solutionDefinition"> <xsf:views> <xsf:view name="Announcement Form"> <xsf:mainpane transform="announcement.xsl"/> </xsf:view> </xsf:views> <xsf:package> <xsf:files> <xsf:file name="announcement.xsl"/> <xsf:file name="template.xml"/> <xsf:file name="announcement.xsd"/> </xsf:files> </xsf:package> <xsf:fileNew> <xsf:initialXmlDocument caption="Announcement" href="template.xml"/> </xsf:fileNew> <xsf:documentSchemas> <xsf:documentSchema location="announcement.xsd"/> </xsf:documentSchemas> </xsf:xDocumentClass>
Finally, Figure 10-4 shows the resulting behavior of the InfoPath editor when the user types in a headline that exceeds 40 characters. Namely, it displays a friendly message alerting the user to the problem.
Figure 10-4. Automatic schema validation in action