Document Designer XSL
Overview
The Document Designer gives admins the option of defining their own custom XSL in order to implement advanced use cases. Using XSL Snippets allows admins access to all data that is stored in a Transaction’s Document XML for use in the Document Designer.
Administration
There are two types of XSL Snippets in the Document Designer that admins can add custom XSL code to:
- Global XSL Snippet
- Inline XSL Snippets
The Global XSL Snippet can be used to create XSL variables that can be referenced in inline XSL Snippets throughout the Document Designer template.
To add XSL to the Global XSL Snippet:
- Open the Document Properties pane (by clicking a blank space in the Admin Action Bar or the Template Flow so that no Layout or Element is selected).
-
In the Dynamic Tool Bar below the Document Properties pane, click the Global XSL button ().
The Global XSL Snippet editor window appears.
- Enter XSL code as needed.
- Optionally, click Validate to check to see if the syntax of the XSL you entered is valid.
- If the syntax is valid, a success message will appear. Click OK to close the message.
- If the syntax is invalid, an error message will appear. Click OK to close the message, and correct the syntax as needed. You will not be able to save the Global XSL Snippet until the syntax is valid.
- Click OK to save the Global XSL Snippet.
Inline XSL Snippets can be used to affect the output of the document by referencing XSL variables. XSL variables can be both declared and referenced within an XSL Snippet, or the inline XSL Snippet can reference XSL variables that are already present in the Global XSL Snippet. Inline XSL Snippets can be added to a Section, a Table cell, or a Header and Footer.
To add an XSL Snippet to the template:
- Click Elements in the Properties panel to expand the available elements.
-
Click and drag XSL Snippet into a Section, a Table cell, or a Header and Footer in the Template Flow.
The Script editor window appears.
- Optionally enter a Name and Description for the XSL Snippet for reference.
- Enter XSL code as needed.
- Optionally, click Validate to check to see if the syntax of the XSL you entered is valid.
- If the syntax is valid, a success message will appear. Click OK to close the message.
- If the syntax is invalid, an error message will appear. Click OK to close the message, and correct the syntax as needed. You will not be able to save the inline XSL Snippet until the syntax is valid.
- Click OK to save the inline XSL Snippet.
Access Parent Loop Document Number from a Nested Loop
Oracle CPQ Release 18A allows administrators to add nested tables within tables, enabling the display of hierarchical information in the output document. For example: Customers can create a quote format that includes a table within a table structure. They can create a table of configurations, where each configuration displays a table of products grouped and sub-totaled by product type (e.g. hardware, software, maintenance).
Using the below use case example, administrators can preview and print a Line Item Grid-style table containing nested Transaction elements. By looping over a parent Document Number in Document Designer or Email Designer, a variable is exposed that always refers to the Document Number of the parent loop’s current Line Item.
Complete the following steps to preview and print a Line Item Grid-style table containing nested Transaction elements:
- Create a Transaction with multiple models and multiple parts for each model.
- Open a Document Designer template.
- Add a container, such as a section or table row, that supports loops.
- Create a loop on the container.
-
Set the Loop On value to Model Line Items.
-
Click Advanced.
The Advanced Loop dialog opens.
-
Add the following code before <CONTENT_REPLACE_TOKEN/>:
<xsl:variable name="modelLoopDocNumber" select="./_document_number"/>
- Click OK.
- Add another loopable element, such as a table or a text field, inside the container.
- Add a loop to the new element.
-
Select Yes to apply a Filter.
-
Add the following to the filter editor:
1. Parent Document Number [_parent_doc_number] (Sub-Document Attribute)
2. = (Operator)
3. $modelLoopDocNumber (XSL Variable) - Click OK.
- Save template.
- Click Preview.
- Enter the BS_ID of the Transaction from Step 1 to view the nested elements.
Use Cases
Using a multi-select menu to attach PDFs to an output Document
Using a recursive template, it is possible to attach multiple PDFs to an output document, based on the user's selections in a multi-select menu.
Using the following method, which is site agnostic and optimized for a multi-language output, only one multi-select menu is required.
In the example, the value of the multi-select menu is used to construct the file's URL in the File Manager. The file format is [langaugeAbbreviation][MSM Variable Value].pdf.
-
Add the following code to the Edit Custom Master Layouts page in the Document Designer or Document Engine:
<fo:simple-page-master master-name="pdfPage" page-height="11in" page-width="8.5in" margin-top="0in" margin-bottom="0in" margin-left="0in" margin-right="0in">
<fo:region-body/>
</fo:simple-page-master>
<!-- Page sequence -->
<fo:page-sequence-master master-name="pdfPageSequence">
<fo:repeatable-page-master-alternatives>
<fo:conditional-page-master-reference master-reference="pdfPage" page-position="any"/>
</fo:repeatable-page-master-alternatives>
</fo:page-sequence-master> -
Add the following templates to the Global XSL Snippet:
<xsl:template name="printablePDF">
<!-- outputs a page with a background image from the URL passed
if URL is blank, this will output a blank page. This is used to attach data sheets. PDFs will output the full number of pages
These are generally stored in the file manager. Use Edit Custom Master Templates in doc engine to modify master-ref pdfPageSequence-->
<xsl:param name="insertURL"/>
<fo:page-sequence content-width="95%" content-height="95%" background-image="{$insertURL}" background-repeat="paginate" master-reference="pdfPageSequence">
<fo:flow flow-name="xsl-region-body">
<fo:block><!--xsl:value-of select="$insertURL" /--></fo:block>
</fo:flow>
</fo:page-seqence>
</xsl:template>
<xsl:template name="genDataSheets">
<!-- this template breaks apart includeDataSheet_quote attribute and builds a file URL from each value.
NOTICE: menu value must match filename of PDF MINUS language prefix and file extension, which are appended here-->
<xsl:param name="sheetList" />
<xsl:param name="sheetLanguage" />
<xsl:variable name="delim">~</xsl:variable> <!--delimiter between values in includeDataSheet_quote, which is a multi-select menu-->
<xsl:variable name="fileExt">.pdf</xsl:variable> <!-- fileExt could be made into a parameter for outputting image pages, etc-->
<xsl:variable name="thisDataSheet">
<xsl:choose>
<xsl:when test="contains($sheetList, $delim)"><xsl:value-of select="normalize-space(substring-before($sheetList,$delim))" /></xsl:when>
<xsl:otherwise><xsl:value-of select="$sheetList" /></xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:if test="$thisDataSheet !=''">
<!-- Note: beware of file name/location or language changes - check file manager or go to url built here if data sheet is missing-->
<xsl:call-template name="printablePDF">
<xsl:with-param name="insertURL" select="concat('/bmfsweb/', $main_doc/site_quote, '/image/Proposal/', 'en', $thisDataSheet, $fileExt)"/>
<!-- !!!MD TODO: english-only data sheets until translated ones come in - then replace 'en' above with $sheetLanguage. -->
</xsl:call-template>
</xsl:if>
<xsl:variable name="rest" select="substring-after($sheetList,$delim)" />
<xsl:if test="$rest != ''">
<xsl:call-template name="genDataSheets">
<xsl:with-param name="sheetList" select="$rest" />
<xsl:with-param name="sheetLanguage" select="$sheetLanguage" />
</xsl:call-template>
</xsl:if> <!--xsl:if test="$rest = ''"></xsl:if-->
</xsl:template>
-
Create a custom XSL page in the Document Designer or Document Engine that calls the recursive template, passing the value of the multi-select menu, as well as the language with the following code.
<!-- This snippet will attach any data sheets selected (assuming the files reside in file manager -->
<!-- Note: see globalXSL snippet for template definition. See also Custom Master Layout used by the template -->
<xsl:if test="$main_doc/includeDataSheet_quote != ''">
<xsl:call-template name="genDataSheets">
<xsl:with-param name="sheetList" select="$main_doc/includeDataSheet_quote" />
<xsl:with-param name="sheetLanguage" select="$main_doc/outputLanguage_quote" />
</xsl:call-template>
</xsl:if>
Use the Commerce Attribute site_quote to specify the site-specific portion of the file's URL within the File Manager.
Attaching images in the document using the file attachment Attribute
In the following example, an XSL Snippet is used to attach an image in the document. This image is dynamically uploaded to the Quote by the user using the file attachment Attribute.
<xsl:variable name="main_doc" select="/transaction/data_xml/document[@document_var_name='quote_process']"/>
<xsl:if test="string-length($main_doc/logo_quote) > 0">
<xsl:variable name="attachLogo" select="concat('http://', $main_doc/creatorCompany_quote, '.bigmachines.com/servlet/ImageServer?&file_type=cmAttachmentAttr&file_id=',$main_doc/logo_quote)"/>
<fo:block>
<fo:external-graphic src="{$attachLogo}" content-height="1.5in" height="1.5in"/>
</fo:block>
</xsl:if>
creatorCompany_quote
is a Commerce attribute which has the value of lower Attribute, _system_supplier_company_name
.
This is used to have relative path in the Document Designer or Document Engine.
logo_quote
is the file attachment attribute used.
Implementing toUpper & toLower
You may want to make a String all uppercase or lowercase before performing comparisons or String operations. The following sample code shows a simple way to convert a String to all lowercase using toLower
<xsl:param name="strToConvert" />
<xsl:value-of select="normalize-space(translate($strToConvert,'ABCDEFGHIJKLMNOPQRSTUVWXYZÀÁÂÃÄÅÈÉÊËÌÍÎÏÑÒÓÔÕÖÙÚÛÜCC', 'abcdefghijklmnopqrstuvwxyzàáâãäåèéêëìíîïñòóôõöùúûücc'))" />
</xsl:template>
If the second and third parameters in "translate" are reversed, then this template becomes toUpper
and the String converts to all uppercase:
<xsl:template name="toUpper">
<xsl:param name="strToConvert" />
<xsl:value-of select="normalize-space(translate($strToConvert, 'abcdefghijklmnopqrstuvwxyzàáâãäåèéêëìíîïñòóôõöùúûücc', 'ABCDEFGHIJKLMNOPQRSTUVWXYZÀÁÂÃÄÅÈÉÊËÌÍÎÏÑÒÓÔÕÖÙÚÛÜCC'))" />
</xsl:template>