Publishing Custom Data Files using the XslHandler

The XslHandler is a special /wiki/spaces/DOC3/pages/2033253 with any given form. It provides the ability to publish data collected by AssetTrack into text files with a custom format.  This can be handy when designing AssetTrack integration with other systems. For example, the XslHander can generate custom CSV or XML files that would be consumed by a customer script.

The customization of these output files is done by applying an XSL style sheet to an XML representation of the data. To understand how the XslHandler functions, consider the following flow of data from an AssetTrack form to the output file:

On this page:


 

The high-level process for using the XslHandler:

  1. Decide on the data needs for your output file (i.e. what headings, data points, delimiters, etc. need to be present in the output)
  2. Create a format definition file that matches the format defined above
  3. Create a form that publishes with the XslHandler, configured to use the newly created format definition file
  4. Publish some test data, and verify the output is what you intended on capturing

XslHandler format definitions

An XslHandler format definition is a standard XSL v1.0 style sheet (XSLT) that will be applied to an XML representation of a combination of form data and repository data from AssetTrack.

Each sample format definition file above contains three primary sections that control what the output file will look like:

  1. A section for defining a variable specifying the document delimiter you would like to use. *
    1. The setting of this variable is optional, but it is required to properly escape values if generating a delimited output file (see display_delim_field).
    2. It is important to note that the variable is utilized in a helper template that encapsulates values with the delimiter present in quotes. 
  2. An optional section for specifying what headers will be included. *
    1. Omitting this section or making it empty will generate a file without any output headers
  3. A section specifying the data to output for each record of asset / purchase order data.

* Optional - Relevant if the style sheet drives generation of a tab- or comma-delimited file

Adding a new XSL file and associating it with a form

Before a form can be associated with a given custom format definition, the file defining that custom format must be uploaded to the server. This can be achieved by logging into the AssetTrack server and navigating Settings > File Integration > File publishing formats

After the custom format definition file has been uploaded, it will be available in the form designer. To associate that format with for a form:

  1. In the Console, open the form
  2. Open the Publishing settings
  3. Select the XslHandler (add it if not already added to the form)
  4. Select the drop-down control for the Format definition file property
  5. Select the desired custom format defintion
  6. Save the form

Now all data published from that form (either automatically or from the form's queue), should result in the data being saved to a file with the format specified by the format definition file.

The file extension of the output can also be specified in the form designer. Simply provide the extension you want in field labeled "Filename extension".

Working example

The default Web Receive form

The default Web Receive form captures the following information:

  • Location, down to 3 levels in the hierarchy
  • PO number (this value is in no way related to the Procurement module's Purchase Order Number)
  • Model of the asset
  • Serial number of an asset
  • Comment (Form-level Named field)

Consider the goal of automatically generating a comma-delimited file with the following information for each row of collected asset data whenever a user submits the form:

  • Form Name
  • User Id
  • Asset Name
  • Asset Tag
  • Asset Serial Number
  • Model Name
  • Model External Id
  • Asset Type Name
  • Status
  • PO Number
  • Comment
  • Floor Name

To achieve this:

  1. Author a format definition (XSL Style Sheet) that:
    1. Sets the delimiter XSL variable to the baked-in value of $delimComma
    2. Specifies the output headers defined above in the /TaskData['OutputHeaders=true'] template match
    3. Specifies the data selects necessary to populate each data row in the Asset template match
    4. The resulting file should look like the sample template definition for Asset forms.
  2. Upload the format definition to AssetTrack under the server's File integration settings section, providing a friendly label to use in the form designer of the console
  3. Open the console, and open the Web Receive form's designer
  4. Under the publishing tab, add the XslHandler, and populate the Format definition file setting under the Handler settings section
  5. Under the publishing tab, ensure the checkbox for Automatically submit data collected via this form is checked
  6. Save the form

Now whenever a user fills in the Web Receive form, a file will be published containing the output of applying the Format definition style sheet against the standard AssetTrack XML data.

Consider the following example where a user captures data for an asset with the following data:

Then a user fills in the Receive form with the following information:

Publishing this form data, using the XslHandler, generates an XML representation of the asset data for the Format definition to be applied against, and the following CSV file is saved to the location specified in the AssetTrack server's File integration settings section.

Form Name,User Id,Asset Name,Asset Tag,Serial Number,Model Name,Asset Type,Status,PO Number,Comment,Floor Name,Floor Code
Web Receive,admin,A07 Name,A07,S07,UltraVOIP,VOIP Desk Phone,Received,PO Test,"Test, Comment",Downtown

Subtle points to consider 

  • By using the display_delim_field helper template, the named field output was conditionally wrapped in quotes because the value contained the delimiter
  • Although AssetTrack's data said that the asset had a location of Los Angeles > Farmington > "The Barn", the form data of Seattle > Downtown > Headquarters is what was collected in the form.  The Seattle location was the value generated in the XML and pulled out by the custom format definition.

The AssetTrack XML format

The table below shows the XML elements and attribute values available in a single record to be transformed by the format definition file.  There are two different XML data formats, specific to each type of form data supported by the XslHandler.  For your convenience, here are two example representations of Asset and Procurement XML data, against which the custom format definition will be applied. 

A special case worth mentioning is DateTime values.  AssetTrack stores date time values in UTC format.  For convenience, each date time value associated with a given element is output in multiple formats, and suffixed with a label that explains its meaning.

  • [No Suffix]: The UTC date and time value - 2012-06-12 11:42:38Z
  • UtcCultureFull: The UTC date and time values, represented in the culture specified by the server's 'Display date format' setting - 6/12/2012 11:42:38 AM
  • UtcCultureDate: The UTC date value, represented in the culture specified by the server's 'Display date format' setting - 6/12/2012
  • UtcCultureTime: The UTC time value, represented in the culture specified by the server's 'Display date format' setting - 11:42 AM
  • TimeZoneAsUtc:  The time-zone adjusted value, represented in UTC format - 2012-06-12 04:42:38Z
  • TimeZoneCultureFull:  The time-zone adjusted, culture-specific representation of the full date and time values - 6/12/2012 4:42:38 AM
  • TimeZoneCultureDate:  The time-zone adjusted, culture-specific representation of the date value - 6/12/2012
  • TimeZoneCultureTime:  The time-zone adjusted, culture-specific representation of the time value - 4:42 AM
Many elements are available in both Asset and Procurement contexts.  The first two columns below show the context-specific path you should use for each element within the XML data.
Asset form data element pathProcurement form data element pathAttributes
/TaskData/CollectionContext/TaskData/CollectionContext
  • Application
  • DeviceId
  • TaskName
  • TaskId
  • TransactionId
  • UserId
  • DateCollected
  • DateCollected_UtcCultureFull
  • DateCollected_UtcCultureDate
  • DateCollected_UtcCultureTime
  • DateCollected_TimeZoneAsUtc
  • DateCollected_TimeZoneCultureFull
  • DateCollected_TimeZoneCultureDate
  • DateCollected_TimeZoneCultureTime
N/A. (the purchase order element)
  • ExternalId
  • Number
  • Status
N/A./PurchaseOrderLineItem
  • ExternalId
  • LineItemNumber
  • QuantityOrdered
  • QuantityReceived
  • Description
  • Consumable
  • ManagedAsset
  • Collected *

* Value represents either the number of consumables or assets collected against a line item for a given form's collection session

N/A./PurchaseOrderLineItem/Sku
  • ExternalId
  • ManufacturerSku
  • PcnDescription
  • Description

. (the asset element)

./PurchaseOrderLineItem/Asset
  • EntityOperation
  • ExternalId
  • AssetTag
  • SerialNumber
  • MacAddress
  • CustomKey1
  • CustomKey2
  • PONumber
  • Status
  • ServiceStatus
  • Description
  • AssetName
  • HostName
  • Cost
  • CAFloorLocation
  • CARoomLocation
  • CACabinetLocation
  • CAShelfLocation
  • CASlotLocation
  • LeaseEndDate
  • LeaseEndDate_UtcCultureFull
  • LeaseEndDate_UtcCultureDate
  • LeaseEndDate_UtcCultureTime
  • LeaseEndDate_TimeZoneAsUtc
  • LeaseEndDate_TimeZoneCultureFull
  • LeaseEndDate_TimeZoneCultureDate
  • LeaseEndDate_TimeZoneCultureTime
  • WarrantyEndDate
  • WarrantyEndDate_UtcCultureFull
  • WarrantyEndDate_UtcCultureDate
  • WarrantyEndDate_UtcCultureTime
  • WarrantyEndDate_TimeZoneAsUtc
  • WarrantyEndDate_TimeZoneCultureFull
  • WarrantyEndDate_TimeZoneCultureDate
  • WarrantyEndDate_TimeZoneCultureTime
./Assignee./PurchaseOrderLineItem/Asset/Assignee
  • ExternalId
  • FirstName
  • LastName
  • FullName
  • Tag
  • Code
./Location 1./PurchaseOrderLineItem/Asset/Location 1
  • ExternalId
  • Name
  • Code
./Organization 1./PurchaseOrderLineItem/Asset/Organization 1
  • ExternalId
  • Name
  • Code
  • Tag
./Product./PurchaseOrderLineItem/Asset/Product
  • ExternalId
  • Name
  • Number
  • PartControlNumber
  • Description
./Product/Manufacturer./PurchaseOrderLineItem/Asset/Product/Manufacturer
  • ExternalId
  • Name
./Product/AssetType 1./PurchaseOrderLineItem/Asset/Product/AssetType 1
  • ExternalId
  • Name
  • Code
  • Tag
./Stockroom./PurchaseOrderLineItem/Asset/Stockroom
  • ExternalId
  • Name
  • Code
  • Tag
  • Type
./Vendor./PurchaseOrderLineItem/Asset/Vendor
  • ExternalId
  • Name
  • Code
  • Tag
./CostCenter./PurchaseOrderLineItem/Asset/CostCenter
  • ExternalId
  • Name
  • Code
  • Tag
./CustomEntity1./PurchaseOrderLineItem/Asset/CustomEntity1
  • ExternalId
  • Name
  • Code
  • Tag
./CustomEntity2./PurchaseOrderLineItem/Asset/CustomEntity2
  • ExternalId
  • Name
  • Code
  • Tag
./CustomEntity3./PurchaseOrderLineItem/Asset/CustomEntity3
  • ExternalId
  • Name
  • Code
  • Tag
./CustomEntity4./PurchaseOrderLineItem/Asset/CustomEntity4
  • ExternalId
  • Name
  • Code
  • Tag
./CustomFieldList/CustomField

../../CustomFieldList/CustomField (purchase order custom field)

../CustomFieldList/CustomField (purchase order line item custom field)

./CustomFieldList/CustomField (asset custom field)

  • Name
  • Alias
  • Value 2
./NamedFieldList/NamedField./NamedFieldList/NamedField (asset form field)
  • Name
  • Alias
  • Value 2 

1 Element can be nested inside itself.  See hierarchicalElementAttributeByDepth for details on using a helper template to output hierarchical values.

2 If the custom or named field is of the type, DateTime, the various DateTime representations of the single value are output as individual attributes of the field element (e.g. <CustomField Name="CustomField_Date" Alias="CustomField_Date" Value="2011-12-14 08:00:00Z" Value_UtcCultureFull="12/14/2011 8:00:00 AM" ...)

XSL helper templates

For convenience, to help deal with hierarchical elements and values containing the delimiter, there are built-in helper templates defined that can be called by your format definition.  See the sample format definition file referenced in the working example above to see how them used in context.

display_delim_field

Escapes any special characters that may be present in the value passed in, requires the $delimiter variable to be set

Parameters expected:

  • field - The value that should be wrapped


<xsl:call-template name="display_delim_field"><!-- Application -->
	<xsl:with-param name="field" select="/TaskData/CollectionContext/@Application" />
</xsl:call-template>

hierarchicalElementAttributeByDepth

Reaches into an hierarchical element, to a specific depth, and pulls out the value of the target attribute specified.

Parameters expected:

  • contextElementNode
  • targetElementName
  • targetAttributeName
  • targetDepth [optional ... will look for the targetAttributeName at the lowest depth found]


<!-- Output the 2nd level Location Name -->
<xsl:call-template name="hierarchicalElementAttributeByDepth">
	<xsl:with-param name="contextElementNode" select="." />
	<xsl:with-param name="targetElementName">Location</xsl:with-param>
	<xsl:with-param name="targetAttributeName">Name</xsl:with-param>
	<xsl:with-param name="targetDepth">2</xsl:with-param>
</xsl:call-template>

replace_string_with_string

Replaces all instances of a string found inside another string

Parameters expected:

  • text
  • replace
  • with

Example:

<!-- Replace all instances of the string'foo' with the string 'bar' in the Asset.Description field -->
<xsl:variable name="newDescription">
	<xsl:call-template name="replace_string_with_string">
		<xsl:with-param name="text" select="./@Description"/>
		<xsl:with-param name="replace" select="'foo'" />
		<xsl:with-param name="with" select="'bar'"/>
	</xsl:call-template>
</xsl:variable>
<xsl:call-template name="display_delim_field">
	<xsl:with-param name="field" select="$newDescription" />
</xsl:call-template>

display_utcdatetime_daydisplay_utcdatetime_monthdisplay_utcdatetime_year

Extracts the day, month and year portions of a UTC representations of a DateTime value

Parameters expected:

  • dateTime - the UTC representation of a date time value for a Date field (e.g. the DateTime field attributes, Value_TimeZoneAsUtc and Value)
  • stripLeadingZeros - strips leading zeros for display_utcdatetime_day and display_utcdatetime_month templates [optional ... will not strip leading zeros if omitted]

Example:

<!--
Given a custom field called, "AcquireDate", and the following element in the XML against which the XSLT is applied:
 
	<CustomField Name="AcquireDate" Alias="AcquireDate"
		Value="2011-06-04 08:00:00Z" Value_UtcCultureFull="6/4/2011 8:00:00 AM" Value_UtcCultureDate="6/4/2011" Value_UtcCultureTime="8:00 AM"
		Value_TimeZoneAsUtc="2011-06-04 00:00:00Z" Value_TimeZoneCultureFull="6/4/2011 12:00:00 AM" Value_TimeZoneCultureDate="6/4/2011" Value_TimeZoneCultureTime="12:00 AM" />
 
We want to output a time-zone-adjusted representation of that value with a custom format not available in the default values (m-d-yyyy): 6-4-2011
-->
 
<xsl:call-template name="display_utcdatetime_month">
	<xsl:with-param name="dateTime" select="./CustomFieldList/CustomField[@Name='AcquireDate']/@Value_TimeZoneAsUtc" />
	<xsl:with-param name="stripLeadingZeros" select="true()" />
</xsl:call-template>
<xsl:value-of select="'-'"/>
<xsl:call-template name="display_utcdatetime_day">
	<xsl:with-param name="dateTime" select="./CustomFieldList/CustomField[@Name='AcquireDate']/@Value_TimeZoneAsUtc" />
	<xsl:with-param name="stripLeadingZeros" select="true()" />
</xsl:call-template>
<xsl:value-of select="'-'"/>
<xsl:call-template name="display_utcdatetime_year">
	<xsl:with-param name="dateTime" select="./CustomFieldList/CustomField[@Name='AcquireDate']/@Value_TimeZoneAsUtc" />
</xsl:call-template>
<xsl:value-of select="$delimiter"/>

Miscellaneous XSLT recipes

Below are recipes for XSLT output requested in the past.

stripDomainFromCollectingUser

Looks for the domain portion of the UserId in the TaskData/CollectionContext. If present, it removes it.


<!-- Set a variable that contains the value from the Uber Dom -->
<xsl:variable name="userIdRaw" select ="/TaskData/CollectionContext/@UserId" />
		
<!--
Set another variable that is populated from:
	a: the value after the backslash if the uber dom value contains a backslash
		OR
	b: the value from the uber dom if the uber dom value DOES NOT contain a backslash
-->
<xsl:variable name="userId">
	<xsl:choose>
		<xsl:when test="contains( $userIdRaw, '\' )">
			<xsl:value-of select="substring-after($userIdRaw, '\')" />
		</xsl:when>
		<xsl:otherwise>
			<xsl:value-of select="$userIdRaw"/>
		</xsl:otherwise>
	</xsl:choose>
</xsl:variable>
		
<!-- Call display_delim_field, passing the $userId value set from the conditional statement above -->
<xsl:call-template name="display_delim_field">
	<xsl:with-param name="field" select="$userId" />
</xsl:call-template>
<xsl:value-of select="$delimiter"/>