XSL: A Swiss Army Knife


QBO 3 make extensive use of eXtensible Stylesheet Language (XSL) transformations. The entire user interface is rendered by passing data through XSLTs.

If you are not familiar with XSL, please check out the W3Schools.com XSL tutorial.

At Quandis, we make heavy use of the 'extensible' part of XSLT, and have the plug-in libraries that can be leveraged from any XSLT. The plugins are defined in /Config/XsltExtension.config. 

Formatting Data

The XsltFormatting extension object provides a number of methods that facilitate formatting data, including:
  • formatMoney(string money):
    <xsl:value-of select="format:formatMoney(UPBAmount)"/> returns 123,456.78
  • formatMoney(string money, string format): 
    <xsl:value-of select="format:formatMoney(UPBAmount, 'C0')"/> returns 123,456
  • formatDate(string date):
    <xsl:value-of select="format:formatMoney(UpdatedDate)"/> returns 12/15/2011
    <xsl:value-of select="format:formatMoney('today')"/> returns 5/22/2012
    <xsl:value-of select="format:formatMoney('yesterday')"/> returns 5/21/2012
    <xsl:value-of select="format:formatMoney('tomorrow')"/> returns 5/23/2012
    <xsl:value-of select="format:formatMoney('first')"/> returns 5/1/2012
    <xsl:value-of select="format:formatMoney('last')"/> returns 5/31/2012
  • formatDate(string date, string format):
    <xsl:value-of select="format:formatMoney(UpdatedDate, 'g')"/> returns 12/15/2011 9:45 AM
    <xsl:value-of select="format:formatMoney(UpdatedDate, 'm')"/> returns Dec 15
    <xsl:value-of select="format:formatMoney(UpdatedDate, 't')"/> returns 9:45 AM
  • isNull(string value, string defaultValue):
    <xsl:value-of select="format:isNull($XmlData/CurrentUPB, //LoanItem/UPBAmount)"/>
  • replace(string source, string oldValue, string newValue):
    <xsl:value-of select="format:replace('Some Field, ' ', '_x0020_'"/> return 'Some_x0020_Field'
  • lastPart(string input, string delimiter):
    <xsl:value-of select="format:lastPart('/Templates/Mortgage/Loan.Search.xslt', '/')"/> returns Loan.Search.xslt
  • dateDiff(string date1, string date2, string interval):
    <xsl:value-of select="format:dateDiff('1/1/2014', '1/15/2014', 'd')"/> returns 14

Rendering Custom Forms from a Summary page

Summary pages have a huge amount of data available to them (from the Summary method), and often have many panels, frequently containing custom forms. 

The AJAX approach to rendering a form:

<div id="myForm" data-behavior="ObjectBind" data-objectbind-options="{{ 'class': 'qbo3.ImportFormObject', 'data': {{'ID': '{$MyImportFormID}' }}, 'method': 'RenderSelect' }}">

The extension object approach to rendering a form:

<div id="myForm" data-behavior="ObjectBind" data-objectbind-options="{{ 'class': 'qbo3.ImportFormObject', 'data': {{'ID': '{$MyImportFormID}' }}, 'method': 'RenderSelect', 'render': false }}">
  <xsl:value-of select="decision:importFormSelect(//ImportFormID[1], .)" disable-output-escaping="yes"/>

 AJAX ApproachExtension Object Approach
  • Less data over the wire = faster load time for rest of page
  • Can leverage custom methods to access "unusual" data
  • Content is available immediately from server
  • Leverages data already available on parent page without re-querying the database
  • User needs to wait for AJAX content to load
  • Queries the database redundantly
  • Limits to same data as the parent page
  • More data over the wire = slower load time for rest of page