Customizing XSL templates
The following example demonstrates how to customize a Question XSL template. The Question XSL template is used when transforming the Intermediate XML. In general, there are other templates that transform the Intermediate XML's corresponding elements. The following sample produces very basic HTML, and does not set all styles.
1 Create an XSL file.
2 Add templates to transform the Question elements.
<xsl:template match="Questions">
<Question>
<xsl:apply-templates select="Question"/>
</Question>
</xsl:template>
3 Add templates to transform the Question elements:
<xsl:template match="Question">
<xsl:param name="bWithinTable" select="false()"/>
<xsl:if test="Style/@ElementAlign = 'NewLine'">
<br/>
</xsl:if>
<xsl:for-each select="*">
<xsl:choose>
<xsl:when test="name() = 'Control'">
<xsl:apply-templates select="."/>
</xsl:when>
<xsl:when test="name() = 'Label'">
<xsl:apply-templates select=".">
<xsl:with-param name="sLabelClass" select="'mrQuestionText'"/>
</xsl:apply-templates>
</xsl:when>
<xsl:when test="name() = 'Error'">
<xsl:apply-templates select=".">
<xsl:with-param name="sLabelClass" select="'mrErrorText'"/>
</xsl:apply-templates>
</xsl:when>
<xsl:when test="name() = 'Table'">
<xsl:apply-templates select=".">
<xsl:with-param name="Orientation" select="../Style/@Orientation" />
</xsl:apply-templates>
</xsl:when>
<xsl:when test="name() = 'Questions'">
<xsl:apply-templates/>
</xsl:when>
</xsl:choose>
</xsl:for-each>
</xsl:template>
4 Add templates to transform the Table elements:
<xsl:template match="Table">
<xsl:element name="span">
<xsl:if test="$bIncludeCSSStyles">
<xsl:attribute name="class">mrQuestionTable</xsl:attribute>
</xsl:if>
<xsl:for-each select="parent::node()">
<xsl:attribute name="style">
<xsl:text>display:block;</xsl:text>
<xsl:call-template name="TableStyle"/>
</xsl:attribute>
</xsl:for-each>
<xsl:call-template name="Row"/>
</xsl:element>
</xsl:template>
<xsl:template name="TableStyle">
<!--- adds the table styles to a style attribute -->
<xsl:call-template name="LabelStyle"/>
</xsl:template>
5 Add templates to transform the Row elements:
<xsl:template name="Row">
<xsl:for-each select="Row">
<xsl:sort select="@Y" order="ascending" data-type="number"/>
<xsl:call-template name="Cell"/>
</xsl:for-each>
</xsl:template>
6 Add templates to transform the Cell elements:
<xsl:template name="Cell">
<xsl:for-each select="Cell">
<xsl:sort select="@X" order="ascending" data-type="number" />
<xsl:for-each select="*">
<xsl:choose>
<xsl:when test="name() = 'Control'">
<xsl:apply-templates select="."/>
</xsl:when>
<xsl:when test="name() = 'Label'">
<xsl:apply-templates select=".">
<xsl:with-param name="sLabelClass" select="'mrQuestionText'"/>
<xsl:with-param name="bWithinTable" select="true()"/>
</xsl:apply-templates>
</xsl:when>
<xsl:when test="name() = 'Error'">
<xsl:apply-templates select=".">
<xsl:with-param name="sLabelClass" select="'mrErrorText'"/>
<xsl:with-param name="bWithinTable" select="true()"/>
</xsl:apply-templates>
</xsl:when>
<xsl:when test="name() = 'Table'">
<xsl:apply-templates select="."/>
</xsl:when>
<xsl:when test="name() = 'Question'">
<xsl:apply-templates select=".">
<xsl:with-param name="bWithinTable" select="true()"/>
</xsl:apply-templates>
</xsl:when>
</xsl:choose>
</xsl:for-each>
</xsl:for-each>
</xsl:template>
Note This template does not handle the cell style. Refer to the default Question.xsl template to set the style.
7 Add templates to transform the Control elements. You can transform corresponding controls against the Control Type attribute:
<xsl:template match="Control">
<xsl:if test="Style/@ElementAlign = 'NewLine'">
<br/>
</xsl:if>
<xsl:choose>
<xsl:when test="@Type = 'RadioButton'">
<xsl:call-template name="RadioButtonControl"/>
</xsl:when>
<xsl:when test="@Type = 'CheckButton'">
<xsl:call-template name="CheckButtonControl"/>
</xsl:when>
<xsl:otherwise>
<xsl:call-template name="StaticControl"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template name="StaticControl">
<xsl:element name="span">
<xsl:attribute name="style">
<xsl:if test="Style/@Width or Style/@Height">
<xsl:call-template name="SpanStyle"/>
</xsl:if>
<xsl:call-template name="ControlStyle"/>
</xsl:attribute>
<xsl:for-each select="Category">
<xsl:apply-templates select="Label">
<xsl:with-param name="sLabelClass" select="'mrShowText'"/>
</xsl:apply-templates>
</xsl:for-each>
</xsl:element>
</xsl:template>
<xsl:template name="RadioButtonControl">
<!--- Control Label -->
<xsl:element name="input">
<!--- Set Control Type -->
<xsl:attribute name="type">radio</xsl:attribute>
<!--- Input name -->
<xsl:attribute name="name">
<xsl:value-of select="@QuestionName"/>
</xsl:attribute>
<!--- ID -->
<xsl:if test="$bIncludeElementIds">
<xsl:attribute name="id">
<xsl:value-of select="@ElementID"/>
<xsl:if test="Category[1]/@CategoryID">
<xsl:value-of select="Category[1]/@CategoryID"/>
</xsl:if>
</xsl:attribute>
</xsl:if>
<!--- CSS Class -->
<xsl:if test="$bIncludeCSSStyles">
<xsl:attribute name="class">mrSingle</xsl:attribute>
</xsl:if>
<!--- Show Only -->
<xsl:if test="$bShowOnly != false()">
<xsl:attribute name="disabled"/>
</xsl:if>
<!--- Read Only -->
<xsl:if test="Style/Control/@ReadOnly = 'true'">
<xsl:attribute name="disabled"/>
</xsl:if>
<!--- Accelerator access key -->
<xsl:if test="Style/Control/@Accelerator != ''">
<xsl:attribute name="accesskey">
<xsl:value-of select="Style/Control/@Accelerator"/>
</xsl:attribute>
</xsl:if>
<!--- Set Control Style -->
<xsl:attribute name="style">
<xsl:call-template name="ControlStyle"/>
</xsl:attribute>
<!--- Button Category -->
<xsl:attribute name="value">
<xsl:if test="Category[1]/@Name">
<xsl:value-of select="Category[1]/@Name"/>
</xsl:if>
</xsl:attribute>
<!--- Is Button Checked -->
<xsl:if test="Category[1]/@Checked = 'true'">
<xsl:attribute name="checked"/>
</xsl:if>
<xsl:choose>
<xsl:when test="$bIncludeElementIds and Category[1]/Label">
<xsl:element name="label">
<xsl:attribute name="for">
<xsl:value-of select="@ElementID"/>
<xsl:if test="Category[1]/@CategoryID">
<xsl:value-of select="Category[1]/@CategoryID"/>
</xsl:if>
</xsl:attribute>
<xsl:apply-templates select="Category[1]/Label">
<xsl:with-param name="sLabelClass" select="'mrSingleText'"/>
</xsl:apply-templates>
</xsl:element>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="Category[1]/Label">
<xsl:with-param name="sLabelClass" select="'mrSingleText'"/>
</xsl:apply-templates>
</xsl:otherwise>
</xsl:choose>
</xsl:element>
</xsl:template>
<xsl:template name="CheckButtonControl">
<!--- Control Label -->
<xsl:element name="input">
<!--- Set Control Type -->
<xsl:attribute name="type">checkbox</xsl:attribute>
<!--- Input name -->
<xsl:attribute name="name">
<xsl:value-of select="@QuestionName"/>
<xsl:if test="Category[1]/@Name">
<xsl:value-of select="Category[1]/@Name"/>
</xsl:if>
</xsl:attribute>
<!--- ID -->
<xsl:if test="$bIncludeElementIds">
<xsl:attribute name="id">
<xsl:value-of select="@ElementID"/>
<xsl:if test="Category[1]/@CategoryID">
<xsl:value-of select="Category[1]/@CategoryID"/>
</xsl:if>
</xsl:attribute>
</xsl:if>
<!--- CSS Class -->
<xsl:if test="$bIncludeCSSStyles">
<xsl:attribute name="class">mrMultiple</xsl:attribute>
</xsl:if>
<!--- Show Only -->
<xsl:if test="$bShowOnly != false()">
<xsl:attribute name="disabled"/>
</xsl:if>
<!--- Read Only -->
<xsl:if test="Style/Control/@ReadOnly = 'true'">
<xsl:attribute name="disabled"/>
</xsl:if>
<!--- Accelerator access key -->
<xsl:if test="Style/Control/@Accelerator != ''">
<xsl:attribute name="accesskey">
<xsl:value-of select="Style/Control/@Accelerator"/>
</xsl:attribute>
</xsl:if>
<!--- Set Control Style -->
<xsl:attribute name="style">
<xsl:call-template name="ControlStyle"/>
</xsl:attribute>
<!--- Button Category -->
<xsl:attribute name="value">
<xsl:if test="Category[1]/@Name">
<xsl:value-of select="Category[1]/@Name"/>
</xsl:if>
</xsl:attribute>
<!--- Is Button Checked -->
<xsl:if test="Category[1]/@Checked = 'true'">
<xsl:attribute name="checked"/>
</xsl:if>
<xsl:choose>
<xsl:when test="$bIncludeElementIds and Category[1]/Label">
<xsl:element name="label">
<xsl:attribute name="for">
<xsl:value-of select="@ElementID"/>
<xsl:if test="Category[1]/@CategoryID">
<xsl:value-of select="Category[1]/@CategoryID"/>
</xsl:if>
</xsl:attribute>
<xsl:apply-templates select="Category[1]/Label">
<xsl:with-param name="sLabelClass" select="'mrMultipleText'"/>
</xsl:apply-templates>
</xsl:element>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="Category[1]/Label">
<xsl:with-param name="sLabelClass" select="'mrMultipleText'"/>
</xsl:apply-templates>
</xsl:otherwise>
</xsl:choose>
</xsl:element>
</xsl:template>
Note This sample transforms the CheckButton control. Refer to the default Question.xsl template to add other control types.
8 Add templates to transform the Control style:
<xsl:template name="ControlStyle">
<!--- adds the control styles to a style attribute -->
<xsl:call-template name="LabelStyle"/>
</xsl:template>
<xsl:template name="LabelStyle">
<!--- adds the label styles to a style attribute -->
<xsl:if test="Style/@BgColor">background-color: <xsl:value-of select="Style/@BgColor"/>;</xsl:if>
<xsl:if test="Style/@Color">color: <xsl:value-of select="Style/@Color"/>;</xsl:if>
<xsl:if test="Style/@Indent">margin-left: <xsl:value-of select="Style/@Indent"/>em;</xsl:if>
<xsl:if test="Style/@Width">width: <xsl:value-of select="Style/@Width"/>;</xsl:if>
<xsl:if test="Style/@Height">height: <xsl:value-of select="Style/@Height"/>;</xsl:if>
<xsl:if test="Style/@Hidden = 'true'">visibility: hidden;</xsl:if>
<xsl:if test="Style/@ZIndex">z-index: <xsl:value-of select="Style/@ZIndex"/>;</xsl:if>
<xsl:choose>
<xsl:when test="Style/@Cursor = 'EResize'">cursor: e-resize;</xsl:when>
<xsl:when test="Style/@Cursor = 'NEResize'">cursor: ne-resize;</xsl:when>
<xsl:when test="Style/@Cursor = 'NResize'">cursor: n-resize;</xsl:when>
<xsl:when test="Style/@Cursor = 'NWResize'">cursor: nw-resize;</xsl:when>
<xsl:when test="Style/@Cursor = 'WResize'">cursor: w-resize;</xsl:when>
<xsl:when test="Style/@Cursor = 'SWResize'">cursor: sw-resize;</xsl:when>
<xsl:when test="Style/@Cursor = 'SResize'">cursor: s-resize;</xsl:when>
<xsl:when test="Style/@Cursor = 'SEResize'">cursor: se-resize;</xsl:when>
<xsl:when test="Style/@Cursor">cursor: <xsl:value-of select="Style/@Cursor"/>;</xsl:when>
</xsl:choose>
<xsl:if test="Style/Cell/@Wrap = 'false'">white-space: nowrap;</xsl:if>
<xsl:if test="Style/Font/@Family">font-family: <xsl:value-of select="Style/Font/@Family"/>;</xsl:if>
<xsl:if test="Style/Font/@Size">font-size: <xsl:value-of select="Style/Font/@Size"/>pt;</xsl:if>
<xsl:if test="Style/Font/@IsUnderline = 'true'">text-decoration: underline;</xsl:if>
<xsl:if test="Style/Font/@IsItalic = 'true'">font-style: italic;</xsl:if>
<xsl:if test="Style/Font/@IsBold = 'true'">font-weight: bold;</xsl:if>
<xsl:if test="Style/Font/@IsStrikethrough = 'true'">text-decoration: line-through;</xsl:if>
<xsl:if test="Style/Font/@IsOverline = 'true'">text-decoration: overline;</xsl:if>
<xsl:if test="Style/Font/@IsBlink = 'true'">text-decoration: blink;</xsl:if>
<xsl:if test="Style/Font/@IsSubscript = 'true'">vertical-align: sub;</xsl:if>
<xsl:if test="Style/Font/@IsSuperscript = 'true'">vertical-align: super;</xsl:if>
</xsl:template>
9 Add templates to transform the Label and Error elements:
<xsl:template match="Label | Error">
<xsl:param name="sLabelClass" select="'UNKNOWN'"/>
<xsl:param name="bWithinTable" select="false()"/>
<xsl:choose>
<xsl:when test="$bIncludeElementIds and @ElementId != ''">
<xsl:element name="label">
<xsl:attribute name="for">
<xsl:value-of select="@ElementId"/>
</xsl:attribute>
<xsl:call-template name="LabelBase">
<xsl:with-param name="sLabelClass" select="$sLabelClass"/>
<xsl:with-param name="bWithinTable" select="$bWithinTable"/>
</xsl:call-template>
</xsl:element>
</xsl:when>
<xsl:otherwise>
<xsl:call-template name="LabelBase">
<xsl:with-param name="sLabelClass" select="$sLabelClass"/>
<xsl:with-param name="bWithinTable" select="$bWithinTable"/>
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template name="LabelBase">
<xsl:param name="sLabelClass" select="'UNKNOWN'"/>
<xsl:param name="bWithinTable" select="false()"/>
<xsl:if test="Style/@ElementAlign = 'NewLine'">
<br/>
</xsl:if>
<xsl:call-template name="Label"/>
</xsl:template>
<xsl:template name="Label">
<xsl:choose>
<xsl:when test="Style/@Image != ''">
<xsl:choose>
<xsl:when test="Style/@ImagePosition = 'Left' or not(Style/@ImagePosition)">
<xsl:element name="img">
<xsl:attribute name="src">
<xsl:if test="not((starts-with(Style/@Image, 'http:'))or(starts-with(Style/@Image, 'https:')))">
<xsl:value-of select="$sImageLocation"/>
</xsl:if>
<xsl:value-of select="Style/@Image"/>
</xsl:attribute>
<xsl:attribute name="alt"/>
</xsl:element>
<xsl:call-template name="LabelText"/>
</xsl:when>
<xsl:when test="Style/@ImagePosition = 'Right'">
<xsl:call-template name="LabelText"/>
<xsl:element name="img">
<xsl:attribute name="src">
<xsl:if test="not((starts-with(Style/@Image, 'http:'))or(starts-with(Style/@Image, 'https:')))">
<xsl:value-of select="$sImageLocation"/>
</xsl:if>
<xsl:value-of select="Style/@Image"/>
</xsl:attribute>
<xsl:attribute name="alt"/>
</xsl:element>
</xsl:when>
<xsl:when test="Style/@ImagePosition = 'Top'">
<xsl:element name="div">
<xsl:element name="img">
<xsl:attribute name="src">
<xsl:if test="not((starts-with(Style/@Image, 'http:'))or(starts-with(Style/@Image, 'https:')))">
<xsl:value-of select="$sImageLocation"/>
</xsl:if>
<xsl:value-of select="Style/@Image"/>
</xsl:attribute>
<xsl:attribute name="alt"/>
</xsl:element>
</xsl:element>
<xsl:call-template name="LabelText"/>
</xsl:when>
<xsl:when test="Style/@ImagePosition = 'Bottom'">
<xsl:element name="div">
<xsl:call-template name="LabelText"/>
</xsl:element>
<xsl:element name="img">
<xsl:attribute name="src">
<xsl:if test="not((starts-with(Style/@Image, 'http:'))or(starts-with(Style/@Image, 'https:')))">
<xsl:value-of select="$sImageLocation"/>
</xsl:if>
<xsl:value-of select="Style/@Image"/>
</xsl:attribute>
<xsl:attribute name="alt"/>
</xsl:element>
</xsl:when>
<xsl:when test="Style/@ImagePosition = 'ImageOnly'">
<xsl:element name="img">
<xsl:attribute name="src">
<xsl:if test="not((starts-with(Style/@Image, 'http:'))or(starts-with(Style/@Image, 'https:')))">
<xsl:value-of select="$sImageLocation"/>
</xsl:if>
<xsl:value-of select="Style/@Image"/>
</xsl:attribute>
<xsl:attribute name="alt">
<xsl:value-of select="Text"/>
</xsl:attribute>
</xsl:element>
</xsl:when>
<xsl:otherwise>
<xsl:call-template name="LabelText"/>
</xsl:otherwise>
</xsl:choose>
</xsl:when>
<xsl:otherwise>
<xsl:call-template name="LabelText"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template name="LabelText">
<xsl:choose>
<xsl:when test="Text/@WellFormed = 'false'">
<xsl:value-of select="Text"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of disable-output-escaping = "yes" select="Text"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
10 Set the question XSL template in the Layout template's mrPage node:
<mrPage QuestionXSL="Question.xsl" />
Refer to
Source XSL and schema examples for the entire template source.
Using this template, when a question is defined as:
FavoritePets "What are your favorite household pets?" categorical
{
Dogs,
Goldfish,
Mice,
Cats,
Hamsters
}
defaultanswer ( {Dogs, Cats} );
The corresponding question HTML source would be:
<br/>
<span class="mrQuestionTable" style="display:block;margin-left: 1em;">
<br/>
<input type="checkbox" name="_QFavoritePets_CDogs" class="mrMultiple" style="margin-left: 1em;" value="Dogs">Dogs</input>
<br/>
<input type="checkbox" name="_QFavoritePets_CGoldfish" class="mrMultiple" style="margin-left: 1em;" value="Goldfish">Goldfish</input>
<br/>
<input type="checkbox" name="_QFavoritePets_CMice" class="mrMultiple" style="margin-left: 1em;" value="Mice">Mice</input>
<br/>
<input type="checkbox" name="_QFavoritePets_CCats" class="mrMultiple" style="margin-left: 1em;" value="Cats">Cats</input>
<br/>
<input type="checkbox" name="_QFavoritePets_CHamsters" class="mrMultiple" style="margin-left: 1em;" value="Hamsters">Hamsters</input>
</span>
Note You can add \HKEY_LOCAL_MACHINE\ Software\SPSS\mrInterview\3\Players\DebugDirectory to the registry in order to output the Intermediate XML. This would allow you to debug the XSL files in XML authoring tools. DebugDirectory is a string value. You must ensure the specified directory exists. After setting registry entry, HTML Player will store all Intermediate XML in the directory. The file name contains the session token (a unique identifier for each interview), save point name, and so on.
See
See also