“雨後彎 Swoosh after the rain” / 香港體育建築形之界 Hong Kong Sports Architecture Forms Division / SML.20130331.7D.37298.BW (cropped), © See-ming Lee

Human readable Gravity Forms exports using XSL

We have a client who needs to review a very complex form created in Gravity Forms. The form has many fields, and to make things worse the labels displayed to the user and the labels displayed to the administrator when someone submits the form are different. Because Gravity Forms has an XML export, it occurred to me that I should be able to create some transformational XSL to turn that XML export file into a human readable description of the form.

Here’s a view of the outputted HTML:

130731-181653

The XSL file to create this is as follows:

<xsl:stylesheet version="2.0" 
                xmlns:html="http://www.w3.org/TR/REC-html40"
				xmlns:image="http://www.google.com/schemas/sitemap-image/1.1"
                xmlns:sitemap="http://www.sitemaps.org/schemas/sitemap/0.9"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
	<xsl:output method="html" version="1.0" encoding="UTF-8" indent="yes"/>
	<xsl:template match="/">
		<html xmlns="http://www.w3.org/1999/xhtml">
			<head>
				<title>Form</title>
				<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
				<style type="text/css">
					body {
						font-family: Helvetica, Arial, sans-serif;
						font-size: 13px;
						color: #545353;
					}
					table {
						border: none;
						border-collapse: collapse;
					}
					tr.odd {
						background-color: #eee;
					}
					tbody tr:hover {
						background-color: #ccc;
					}
					tbody tr:hover td, #sitemap tbody tr:hover td a {
						color: #000;
					}
					#content {
						margin: 0 auto;
						width: 1000px;
					}
					td {
						font-size:11px;
						line-height:80%;
						padding: 5px 0;
						vertical-align: top;
					}
					th {
						text-align:left;
						padding-right:30px;
						font-size:11px;
					}
					thead th {
						border-bottom: 1px solid #000;
						cursor: pointer;
					}
				</style>
			</head>
			<body>
				<div id="content">
					<xsl:for-each select="forms/form">
						<h1>Form: <xsl:value-of select="title"/></h1>
						<table cellpadding="3">
							<thead>
								<tr>
									<th width="24%">User Label (field type)</th>
									<th width="23%">Admin Label</th>
									<th width="53%">Choices (if specified, value:label)</th>
								</tr>
							</thead>
							<tbody>
								<xsl:for-each select="fields/field">
									<tr>
										<xsl:choose>
											<xsl:when test="@type='section'">
												<th colspan="3"><xsl:value-of select="label"/> (<xsl:value-of select="@type"/>)</th>
											</xsl:when>
											<xsl:otherwise>
												<td><xsl:value-of select="label"/> (<xsl:value-of select="@type"/>)</td>
												<td><xsl:value-of select="adminLabel"/></td>
												<td>
													<xsl:for-each select="choices/choice">
														<xsl:value-of select="value"/>:<xsl:value-of select="text"/><br />
													</xsl:for-each>
												</td>
											</xsl:otherwise>
										</xsl:choose>
									</tr>
								</xsl:for-each>
							</tbody>
						</table>
					</xsl:for-each>
				</div>
			</body>
		</html>
	</xsl:template>
</xsl:stylesheet>

Create a directory on a webserver somewhere (this is to get around same domain restrictions), then drop the XML export into the directory. Add the XSL file above (copy and paste it) and save it as xsl.xml. Now you need to amend your XML to reference the XSL, which you can do as follows.

The current version of Gravity Forms creates an XML export which looks like this:

<?xml version="1.0" encoding="UTF-8"?>
<forms version="1.7.6">

You need to insert a new line, after the first, which reads like this (note you need to change the directory name):

<?xml-stylesheet type="text/xsl" href="/{your directory name}/xsl.xml"?>

So the top of your XML file ends up looking like:

<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="/{your directory name}/xsl.xml"?>
<forms version="1.7.6">

Note: It is possible to include inline XSL in an XML file, and it might be a nice Gravity Forms feature to be able to open the export in your browser to see an overview of the forms which have been exported.

The XSL shown here is cribbed heavily from Yoast’s XSL for the sitemaps generated by the WordPress SEO plugin. :)

Update – Thursday 01 August 2013

After some brief playing around this morning, with a fresh brain, it’s quite possible to have that XSL inline, as I hinted. Here’s a genuine Gravity Forms export with the inline XSL, so you don’t need to faff around creating directories and viewing on webservers, you’d simply be able to open the export on your local machine using a capable browser (like Chrome or Safari). I’ve also updated the XSL to pull out some form settings, and description, etc.

You can also view this example in your browser. Note that there seems to be a problem with Gravity Forms importing the XML to create the forms, in that the first form doesn’t get imported; I’ve not looked into this yet.

You’ll see from the example below that we’re adding an XSL stylesheet reference to a href which is an ID within the XML document, we’re also adding an inline doctype (if that’s the right terminology) to require the xsl:stylesheet element within the forms element to have an ID. Everything else is much the same as above.

<?xml version="1.0" encoding="UTF-8"?><?xml-stylesheet type="text/xsl" href="#stylesheet"?>
<!DOCTYPE forms [
<!ATTLIST xsl:stylesheet
  id	ID	#REQUIRED>
]><forms version="1.7.6">
	<xsl:stylesheet id="stylesheet"
					version="2.0" 
	                xmlns:html="http://www.w3.org/TR/REC-html40"
					xmlns:image="http://www.google.com/schemas/sitemap-image/1.1"
	                xmlns:sitemap="http://www.sitemaps.org/schemas/sitemap/0.9"
	                xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
		<xsl:output method="html" version="1.0" encoding="UTF-8" indent="yes"/>
		<xsl:template match="/">
			<html xmlns="http://www.w3.org/1999/xhtml">
				<head>
					<title>Form</title>
					<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
					<style type="text/css">
						body {
							font-family: Helvetica, Arial, sans-serif;
							font-size: 13px;
							color: #545353;
						}
						table {
							border: none;
							border-collapse: collapse;
						}
						tr.odd {
							background-color: #eee;
						}
						tbody tr:hover {
							background-color: #ccc;
						}
						tbody tr:hover td, #sitemap tbody tr:hover td a {
							color: #000;
						}
						#content {
							margin: 0 auto;
							width: 1000px;
						}
						td {
							font-size:11px;
							line-height:80%;
							padding: 5px;
							vertical-align: top;
						}
						th {
							text-align:left;
							padding: 5px 30px 5px 5px;
							font-size:11px;
						}
						thead th {
							border-bottom: 1px solid #000;
							cursor: pointer;
						}
					</style>
				</head>
				<body>
					<div id="content">
						<xsl:for-each select="forms/form">
							<h1>Form: <xsl:value-of select="title"/></h1>
							<h2>Description (<xsl:value-of select="descriptionPlacement"/>)</h2>
							<p><xsl:value-of select="description"/></p>
							<h2>Settings</h2>
							<p><strong>Button text:</strong> "<xsl:value-of select="button/text"/>"</p>
							<h2>Fields</h2>
							<table cellpadding="3">
								<thead>
									<tr>
										<th width="24%">User Label (field type)</th>
										<th width="23%">Admin Label</th>
										<th width="53%">Choices (if specified, value:label)</th>
									</tr>
								</thead>
								<tbody>
									<xsl:for-each select="fields/field">
										<tr>
											<xsl:choose>
												<xsl:when test="@type='section'">
													<th colspan="3">
														<xsl:value-of select="label"/><xsl:if test="@isRequired=1"><span title="required">*</span></xsl:if> 
														(<xsl:value-of select="@type"/>)
													</th>
												</xsl:when>
												<xsl:otherwise>
													<td>
														<xsl:value-of select="label"/><xsl:if test="@isRequired=1"><span title="required">*</span></xsl:if>
														(<xsl:value-of select="@type"/>)
													</td>
													<td><xsl:value-of select="adminLabel"/></td>
													<td>
														<xsl:for-each select="choices/choice">
															<xsl:if test="value"><xsl:value-of select="value"/>:</xsl:if><xsl:value-of select="text"/><br />
														</xsl:for-each>
													</td>
												</xsl:otherwise>
											</xsl:choose>
										</tr>
									</xsl:for-each>
								</tbody>
							</table>
						</xsl:for-each>
					</div>
				</body>
			</html>
		</xsl:template>
	</xsl:stylesheet>
	<form labelPlacement="top_label" useCurrentUserAsAuthor="1">
		<title><![CDATA[Example Contact Form ]]></title>
		<description><![CDATA[An example contact form. Duis, ulciscor, bis quis utrum imputo, hendrerit iusto nostrud, refoveo luctus foras nimis. Et vulputate capio occuro ea in vel opto, enim esca. Opes eros plaga suscipere esca in augue pecus et quia consequat veniam. Opto gemino sudo aliquip, vero mos molior sed minim eligo similis, sagaciter praesent sagaciter lobortis. ]]></description>
		<descriptionPlacement><![CDATA[below]]></descriptionPlacement>
		<button type="text">
			<text><![CDATA[Submit]]></text>
		</button>
		<fields>
			<field id="1" type="name" isRequired="1" size="medium">
				<label><![CDATA[Name]]></label>
				<inputs>
					<input id="1.3">
						<label><![CDATA[First]]></label>
					</input>
					<input id="1.6">
						<label><![CDATA[Last]]></label>
					</input>
				</inputs>
			</field>
			<field id="2" type="email" isRequired="1" size="medium">
				<label><![CDATA[Email]]></label>
			</field>
			<field id="3" type="textarea" isRequired="1" size="medium">
				<label><![CDATA[Your message]]></label>
			</field>
		</fields>
		<confirmations>
			<confirmation id="51fa14a0d0c54" isDefault="1" type="message">
				<name><![CDATA[Default Confirmation]]></name>
				<message><![CDATA[Thanks for contacting us! We will get in touch with you shortly.]]></message>
			</confirmation>
		</confirmations>
		<notifications>
			<notification id="51fa14a0d0692">
				<to><![CDATA[{admin_email}]]></to>
				<name><![CDATA[Admin Notification]]></name>
				<event><![CDATA[form_submission]]></event>
				<toType><![CDATA[email]]></toType>
				<subject><![CDATA[New submission from {form_title}]]></subject>
				<message><![CDATA[{all_fields}]]></message>
			</notification>
		</notifications>
	</form>
	<form labelPlacement="top_label" useCurrentUserAsAuthor="1">
		<title><![CDATA[Call back]]></title>
		<descriptionPlacement><![CDATA[below]]></descriptionPlacement>
		<button type="text">
			<text><![CDATA[Call me!]]></text>
		</button>
		<fields>
			<field id="1" isRequired="1" size="medium" type="phone" phoneFormat="international">
				<label><![CDATA[Your phone number]]></label>
			</field>
			<field id="2" isRequired="1" size="medium" type="checkbox">
				<label><![CDATA[When shall we call?]]></label>
				<choices>
					<choice>
						<text><![CDATA[8am – 12pm]]></text>
					</choice>
					<choice>
						<text><![CDATA[12pm – 6pm]]></text>
					</choice>
					<choice>
						<text><![CDATA[6pm – 9pm]]></text>
					</choice>
				</choices>
			</field>
		</fields>
		<confirmations>
			<confirmation id="51fa180b70b68" isDefault="1" type="message">
				<name><![CDATA[Default Confirmation]]></name>
				<message><![CDATA[Thanks for contacting us! We will get in touch with you shortly.]]></message>
			</confirmation>
		</confirmations>
		<notifications>
			<notification id="51fa180b708d4">
				<to><![CDATA[{admin_email}]]></to>
				<name><![CDATA[Admin Notification]]></name>
				<event><![CDATA[form_submission]]></event>
				<toType><![CDATA[email]]></toType>
				<subject><![CDATA[New submission from {form_title}]]></subject>
				<message><![CDATA[{all_fields}]]></message>
			</notification>
		</notifications>
	</form>
</forms>

(Photo: “雨後彎 Swoosh after the rain” / 香港體育建築形之界 Hong Kong Sports Architecture Forms Division / SML.20130331.7D.37298.BW (cropped), © See-ming Lee)

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.