Creating the XSLT template to transform the promotion XML

Create a custom XSLT template to transform the authoring promotion XML to the runtime promotion XML. This transformation takes place when a business user activates a promotion based on your custom promotion type.

Before you begin

Review the following topics to ensure that you understand the role of XSLT templates:

About this task

The Promotions tool provides a set of default XSLT templates. Each default promotion type defined in the Promotions tool is configured to work with certain templates. When you create a custom promotion type, you must create a new custom XSLT template; however, you can copy the content of an existing XSLT template into an empty file and then customize only certain sections.
Typically, you must define a new purchase condition structure for a new promotion type. To develop a new purchase condition XSLT template, you must use information you gathered in two previous steps as input, that is:
  • The purchase condition section of the runtime promotion XML that you modeled
  • The data you determined is required from the Management Center user interface for this particular promotion type

Procedure

  1. Create the XSLT template for the element of the new promotion type that you are customizing. In most cases, this is the <PurchaseCondition> element.

    If you want to use one of the default XSLT templates as a starting point, the templates are stored at this path:

    workspace_dir/WC/xml/config/com.ibm.commerce.promotion/template

    The following table maps each purchase condition XSLT template to its default promotion type:

    XSLT templates mapped to default promotion types
    Purchase condition XSLT template Default promotion type
    CategoryAllItemAmountOffPurchaseConditionTemplate.xsl Amount off the subtotal of catalog entries from a category
    CategoryAllItemFixedCostPurchaseConditionTemplate.xls Fixed price on the subtotal of catalog entries from a category
    CategoryAllItemPercentOffPurchaseConditionTemplate.xsl Percentage off the subtotal of catalog entries from a category
    CategoryFixedCostShippingPurchaseConditionTemplate.xls Buy catalog entries from category X, get shipping at a fixed price
    CategoryPerItemAmountOffPurchaseConditionTemplate.xsl Amount off individual catalog entries from a category
    CategoryPerItemFixedCostPurchaseConditionTemplate.xls Fixed price on individual catalog entries from a category
    CategoryPerItemPercentOffPurchaseConditionTemplate.xsl Percentage off individual catalog entries from a category
    CategoryPurchaseWithPurchasePercentOffPurchaseConditionTemplate.xls Buy catalog entries from category X, get a percentage off catalog entry Y
    CategorySameItemPercentOffPurchaseConditionTemplate.xsl Buy catalog entries from category X, get additional catalog entries from category X at a percentage off
    CategoryWithFreeGiftPurchaseConditionTemplate.xsl Buy catalog entries from category X, get catalog entry Y free
    MultipleItemsGetYFixedAmountOffPurchaseConditionTemplate.xls Buy A (and B and C), get an amount off Y
    MultipleItemsGetYPercentOffPurchaseConditionTemplate.xls Buy A (and B and C), get a percentage off Y
    MultipleItemsPercentOffPurchaseConditionTemplate.xsl Buy A and B, get a percentage off both
    OrderAmountOffPurchaseConditionTemplate.xsl Amount off on order
    OrderFixedAmountOffShippingPurchaseConditionTemplate.xsl Amount off shipping on an order
    OrderFixedCostShippingPurchaseConditionTemplate.xsl Fixed price for shipping an order
    OrderFreeGiftPurchaseConditionTemplate.xsl Free gift with an order
    OrderPercentOffPurchaseConditionTemplate.xsl Percentage off an order
    ProductAllItemAmountOffPurchaseConditionTemplate.xsl Amount off the subtotal of catalog entries
    ProductAllItemFixedCostPurchaseConditionTemplate.xls Fixed price on the subtotal of catalog entries
    ProductAllItemPercentOffPurchaseConditionTemplate.xsl Percentage off the subtotal of catalog entries
    ProductFixedCostShippingPurchaseConditionTemplate.xls Buy catalog entry X, get shipping at a fixed price
    ProductPerItemAmountOffPurchaseConditionTemplate.xsl Amount off individual catalog entries
    ProductPerItemFixedCostPurchaseConditionTemplate.xls Fixed price on individual catalog entries
    ProductPerItemPercentOffPurchaseConditionTemplate.xsl Percentage off individual catalog entries
    ProductPurchaseWithPurchasePercentOffPurchaseConditionTemplate.xsl Buy catalog entry X, get percentage off catalog entry Y
    ProductSameItemPercentOffPurchaseConditionTemplate.xsl Buy catalog entry X, get additional X at a percentage off
    ProductWithFreeGiftPurchaseConditionTemplate.xsl Buy catalog entry X, get catalog entry Y free

    In addition to the purchase condition XSLT templates, there are three additional XSLT templates. These three templates are used for all default promotion types.

    XSLT templates mapped to default promotion types
    Purchase condition XSLT template Purpose
    DefaultTargetingConditionTemplate.xsl Transforms the authoring promotion XML to create the targetingCondition section of the runtime promotion XML.
    DefaultCustomConditionsTemplate.xsl Transforms the authoring promotion XML to create the customCondition section of the runtime promotion XML.
    DefaultBasePromotionTemplate.xsl Transforms the authoring promotion XML to create the basePromotion section of the runtime promotion XML.
  2. Save your custom XSLT template file under the following directory:

    workspace_dir/WC/xml/config/com.ibm.commerce.promotion-ext/template

Example

For your custom promotion type, Customers who purchase two dining chairs (FULO-01) qualify to purchase a dining table (FULO-02) at the reduced price of $200, you create a custom XSL template for the <PurchaseCondition> element called ProductPurchaseWithPurchaseFixedCostPurchaseConditionTemplate.xsl. It looks like the following sample:
<?xml version="1.0" encoding="UTF-8"?> 
   <xsl:transform version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
      <!-- handles purchase condition -->
      <xsl:template name="PurchaseConditionTemplate" match="/">
         <PurchaseCondition impl="com.ibm.commerce.marketing.promotion.condition.PurchaseCondition">
            <Pattern impl="com.ibm.commerce.marketing.promotion.condition.Pattern">
               <Constraint impl="com.ibm.commerce.marketing.promotion.condition.Constraint">
                  <WeightedRange impl="com.ibm.commerce.marketing.promotion.condition.WeightedRange">
                     <LowerBound>
                        <xsl:value-of  select="PromotionData/Elements/PurchaseCondition/Purchase/Data/Quantity" />
                     </LowerBound>
                     <UpperBound>
                        <xsl:value-of  select="PromotionData/Elements/PurchaseCondition/Purchase/Data/Quantity" />
                     </UpperBound>
                     <Weight>1</Weight>
                  </WeightedRange>
                  <FilterChain impl="com.ibm.commerce.marketing.promotion.condition.FilterChain">
                     <Filter impl="com.ibm.commerce.marketing.promotion.condition.MultiSKUFilter">
                        <xsl:for-each  select="PromotionData/Elements/PurchaseCondition/Purchase/IncludeCatalogEntryIdentifier">
                           <IncludeCatEntryKey>
                              <xsl:call-template name="CatalogEntryKeyTemplate">
                                 <xsl:with-param name="dn" select="Data/DN" />
                                 <xsl:with-param name="sku" select="Data/SKU" />
                              </xsl:call-template>
                           </IncludeCatEntryKey>
                        </xsl:for-each>
                        <xsl:for-each select="PromotionData/Elements/PurchaseCondition/Purchase/ExcludeCatalogEntryIdentifier">
                           <ExcludeCatEntryKey>
                              <xsl:call-template name="CatalogEntryKeyTemplate">
                                 <xsl:with-param name="dn" select="Data/DN" />
                                 <xsl:with-param name="sku" select="Data/SKU" />
                              </xsl:call-template>
                           </ExcludeCatEntryKey>
                        </xsl:for-each>
                     </Filter>
                  </FilterChain>
               </Constraint>
               <Constraint impl="com.ibm.commerce.marketing.promotion.condition.Constraint">
                  <WeightedRange impl="com.ibm.commerce.marketing.promotion.condition.WeightedRange">
                     <LowerBound>
                        <xsl:value-of select="PromotionData/Elements/PurchaseCondition/Reward/Data/Quantity" />
                     </LowerBound>
                     <UpperBound>
                        <xsl:value-of select="PromotionData/Elements/PurchaseCondition/Reward/Data/Quantity" />
                     </UpperBound>
                     <Weight>1</Weight>
                  </WeightedRange>
                  <FilterChain impl="com.ibm.commerce.marketing.promotion.condition.FilterChain">
                     <Filter impl="com.ibm.commerce.marketing.promotion.condition.MultiSKUFilter">
                        <xsl:for-each select="PromotionData/Elements/PurchaseCondition/Reward/IncludeCatalogEntryIdentifier">
                           <IncludeCatEntryKey>
                              <xsl:call-template name="CatalogEntryKeyTemplate">
                                 <xsl:with-param name="dn" select="Data/DN" />
                                 <xsl:with-param name="sku" select="Data/SKU" />
                              </xsl:call-template>
                           </IncludeCatEntryKey>
                        </xsl:for-each>
                        <xsl:for-each select="PromotionData/Elements/PurchaseCondition/Reward/ExcludeCatalogEntryIdentifier">
                           <ExcludeCatEntryKey>
                              <xsl:call-template name="CatalogEntryKeyTemplate">
                                 <xsl:with-param name="dn" select="Data/DN" />
                                 <xsl:with-param name="sku" select="Data/SKU" />
                              </xsl:call-template>
                           </ExcludeCatEntryKey>
                        </xsl:for-each>
                     </Filter>
                  </FilterChain>
               </Constraint>
            </Pattern>
            <Distribution impl="com.ibm.commerce.marketing.promotion.reward.Distribution">
               <Type>Volume</Type>
               <Base>Quantity</Base>
               <Currency>
                  <xsl:value-of select="PromotionData/Elements/PurchaseCondition/Data/Currency" />
               </Currency>
               <Range impl="com.ibm.commerce.marketing.promotion.reward.DistributionRange">
                  <LowerBound>1</LowerBound>
                  <UpperBound>-1</UpperBound>
                  <LowerBoundIncluded>true</LowerBoundIncluded>
                  <UpperBoundIncluded>false</UpperBoundIncluded>
                  <RewardChoice>
                     <Reward impl="com.ibm.commerce.marketing.promotion.reward.DefaultReward">
                        <AdjustmentFunction impl="com.ibm.commerce.marketing.promotion.reward.AdjustmentFunction">
                           <FilterChain impl="com.ibm.commerce.marketing.promotion.condition.FilterChain">
                              <Filter impl="com.ibm.commerce.marketing.promotion.condition.MultiSKUFilter">
                                 <xsl:for-each select="PromotionData/Elements/PurchaseCondition/Reward/IncludeCatalogEntryIdentifier">
                                    <IncludeCatEntryKey>
                                       <xsl:call-template name="CatalogEntryKeyTemplate">
                                          <xsl:with-param name="dn" select="Data/DN" />
                                          <xsl:with-param name="sku" select="Data/SKU" />
                                       </xsl:call-template>
                                    </IncludeCatEntryKey>
                                 </xsl:for-each>
                                 <xsl:for-each select="PromotionData/Elements/PurchaseCondition/Reward/ExcludeCatalogEntryIdentifier">
                                    <ExcludeCatEntryKey>
                                       <xsl:call-template name="CatalogEntryKeyTemplate">
                                          <xsl:with-param name="dn" select="Data/DN" />
                                          <xsl:with-param name="sku" select="Data/SKU" />
                                       </xsl:call-template>
                                    </ExcludeCatEntryKey>
                                 </xsl:for-each>
                              </Filter>
                           </FilterChain>
                           <Adjustment impl="com.ibm.commerce.marketing.promotion.reward.FixedCostAdjustment">
                              <FixedCost>
                                 <xsl:value-of select="PromotionData/Elements/PurchaseCondition/Data/FixedCost" />
                              </FixedCost>
                              <AdjustmentType>IndividualAffectedItems</AdjustmentType>
                                 <Currency>
                                    <xsl:value-of select="PromotionData/Elements/PurchaseCondition/Data/Currency" />
                                 </Currency>
                              </Adjustment>
                           </AdjustmentFunction>
                        </Reward>
                     </RewardChoice>
                  </Range>
                  <PatternFilter impl="com.ibm.commerce.marketing.promotion.condition.DummyPatternFilter">
                  </PatternFilter>
               </Distribution>
            </PurchaseCondition>
         </xsl:template>

         <!-- handles CatalogEntryKey -->
         <xsl:template name="CatalogEntryKeyTemplate">
            <xsl:param name="dn" />
            <xsl:param name="sku" />
            <CatalogEntryKey>
               <DN>
                  <xsl:value-of select="$dn" />
               </DN>
               <SKU>
                  <xsl:value-of select="$sku" />
               </SKU>
            </CatalogEntryKey>
         </xsl:template>
      </xsl:transform>
To make a promotion apply to the least expensive item, replace the existing constraints in the CategorySameItemPercentOffPurchaseConditionTemplate.xsl file with the following constraints:
Important: You must first enable ApplyPromotionOnLowestPricedOrderItemsFirst for the constraints to work.
<Constraint impl="com.ibm.commerce.marketing.promotion.condition.Constraint">
	<WeightedRange impl="com.ibm.commerce.marketing.promotion.condition.WeightedRange">
		<LowerBound>
			<xsl:value-of select="PromotionData/Elements/PurchaseCondition/Data/BaseQuantity" />
		</LowerBound>
		<UpperBound>
			<xsl:value-of select="PromotionData/Elements/PurchaseCondition/Data/BaseQuantity" />
		</UpperBound>
		<Weight>1</Weight>
	</WeightedRange>
	<FilterChain impl="com.ibm.commerce.marketing.promotion.condition.FilterChain">
		<Filter impl="com.ibm.commerce.marketing.promotion.condition.CategoryFilter">
			<xsl:for-each select="PromotionData/Elements/PurchaseCondition/IncludeCategoryIdentifier">
				<IncludeCategory>
					<xsl:call-template name="CategoryKeyTemplate">
						<xsl:with-param name="dn" select="Data/DN" />
						<xsl:with-param name="name" select="Data/Name" />
					</xsl:call-template>
				</IncludeCategory>
			</xsl:for-each>
			<xsl:for-each select="PromotionData/Elements/PurchaseCondition/ExcludeCategoryIdentifier">
				<ExcludeCategory>
					<xsl:call-template name="CategoryKeyTemplate">
						<xsl:with-param name="dn" select="Data/DN" />
						<xsl:with-param name="name" select="Data/Name" />
					</xsl:call-template>
				</ExcludeCategory>
			</xsl:for-each>
		</Filter>
		<xsl:choose>
			<xsl:when test="PromotionData/Elements/PurchaseCondition/ExcludeCatalogEntryIdentifier">
			<!-- Only populate when there are exclude items -->
				<Filter impl="com.ibm.commerce.marketing.promotion.condition.MultiSKUFilter">
					<xsl:for-each select="PromotionData/Elements/PurchaseCondition/ExcludeCatalogEntryIdentifier">
						<ExcludeCatEntryKey>
							<xsl:call-template name="CatalogEntryKeyTemplate">
								<xsl:with-param name="dn" select="Data/DN" />
								<xsl:with-param name="sku" select="Data/SKU" />
							</xsl:call-template>
						</ExcludeCatEntryKey>
					</xsl:for-each>
				</Filter>
			</xsl:when>
		</xsl:choose>
		<xsl:choose>
			<xsl:when test="PromotionData/Elements/PurchaseCondition/CatalogEntryAttributeRule">
			<!-- Only populate when there are attributes -->
				<Filter	impl="com.ibm.commerce.marketing.promotion.condition.CatalogEntryAttributeFilter">
					<AssociatedLanguage><xsl:value-of select="PromotionData/Elements/PurchaseCondition/Data/Language" />
                                   </AssociatedLanguage>
					<CaseSensitive>false</CaseSensitive>
					<SupportAttributeWithNoAssociatedLanguage>true</SupportAttributeWithNoAssociatedLanguage>
					<xsl:for-each select="PromotionData/Elements/PurchaseCondition/CatalogEntryAttributeRule">
						<xsl:call-template name="CatalogEntryAttributeRuleTemplate">
							<xsl:with-param name="attributeRule" select="." />
						</xsl:call-template>	
					</xsl:for-each>					
				</Filter>
			</xsl:when>
		</xsl:choose>
		<xsl:choose>
			<xsl:when test="PromotionData/Elements/PurchaseCondition/IncludePaymentTypeIdentifier">
				<xsl:choose>
					<xsl:when test="PromotionData/Elements/PurchaseCondition/IncludePaymentTypeIdentifier/Data/PaymentType != 'Any'">
						<Filter impl="com.ibm.commerce.marketing.promotion.condition.PaymentTypeFilter">
							<IncludePaymentType>
								<PaymentMethodName><xsl:value-of 
select="PromotionData/Elements/PurchaseCondition/IncludePaymentTypeIdentifier/Data/PaymentType" />
                                                        </PaymentMethodName>
							</IncludePaymentType>
						</Filter>
					</xsl:when>
				</xsl:choose>						
			</xsl:when>
		</xsl:choose>						
		<Filter impl="com.ibm.commerce.marketing.promotion.condition.ItemSortingFilter">
			<SortingMethod>PriceHighToLow</SortingMethod>
			<SplitMethod>SplitEndToStart</SplitMethod>    	
		</Filter>								
	</FilterChain>
</Constraint>
<Constraint impl="com.ibm.commerce.marketing.promotion.condition.Constraint">
	<WeightedRange impl="com.ibm.commerce.marketing.promotion.condition.WeightedRange">
		<LowerBound>
			<xsl:value-of select="PromotionData/Elements/PurchaseCondition/Data/RewardQuantity" />
		</LowerBound>
		<UpperBound>
			<xsl:value-of select="PromotionData/Elements/PurchaseCondition/Data/RewardQuantity" />
		</UpperBound>
		<Weight>1</Weight>
	</WeightedRange>
	<FilterChain impl="com.ibm.commerce.marketing.promotion.condition.FilterChain">
		<Filter impl="com.ibm.commerce.marketing.promotion.condition.CategoryFilter">
			<xsl:for-each select="PromotionData/Elements/PurchaseCondition/IncludeCategoryIdentifier">
				<IncludeCategory>
					<xsl:call-template name="CategoryKeyTemplate">
						<xsl:with-param name="dn" select="Data/DN" />
						<xsl:with-param name="name" select="Data/Name" />
					</xsl:call-template>
				</IncludeCategory>
			</xsl:for-each>
			<xsl:for-each select="PromotionData/Elements/PurchaseCondition/ExcludeCategoryIdentifier">
				<ExcludeCategory>
					<xsl:call-template name="CategoryKeyTemplate">
						<xsl:with-param name="dn" select="Data/DN" />
						<xsl:with-param name="name" select="Data/Name" />
					</xsl:call-template>
				</ExcludeCategory>
			</xsl:for-each>
		</Filter>
		<xsl:choose>
			<xsl:when test="PromotionData/Elements/PurchaseCondition/ExcludeCatalogEntryIdentifier">
			<!-- Only populate when there are exclude items -->
				<Filter impl="com.ibm.commerce.marketing.promotion.condition.MultiSKUFilter">
					<xsl:for-each select="PromotionData/Elements/PurchaseCondition/ExcludeCatalogEntryIdentifier">
						<ExcludeCatEntryKey>
							<xsl:call-template name="CatalogEntryKeyTemplate">
								<xsl:with-param name="dn" select="Data/DN" />
								<xsl:with-param name="sku" select="Data/SKU" />
							</xsl:call-template>
						</ExcludeCatEntryKey>
					</xsl:for-each>
				</Filter>
			</xsl:when>
		</xsl:choose>
		<xsl:choose>
			<xsl:when test="PromotionData/Elements/PurchaseCondition/CatalogEntryAttributeRule">
			<!-- Only populate when there are attributes -->
				<Filter
					impl="com.ibm.commerce.marketing.promotion.condition.CatalogEntryAttributeFilter">
					<AssociatedLanguage><xsl:value-of select="PromotionData/Elements/PurchaseCondition/Data/Language" />
                                   </AssociatedLanguage>
					<CaseSensitive>false</CaseSensitive>
					<SupportAttributeWithNoAssociatedLanguage>true</SupportAttributeWithNoAssociatedLanguage>
					<xsl:for-each select="PromotionData/Elements/PurchaseCondition/CatalogEntryAttributeRule">
						<xsl:call-template name="CatalogEntryAttributeRuleTemplate">
							<xsl:with-param name="attributeRule" select="." />
						</xsl:call-template>	
					</xsl:for-each>					
				</Filter>
			</xsl:when>
		</xsl:choose>
		<xsl:choose>
			<xsl:when test="PromotionData/Elements/PurchaseCondition/IncludePaymentTypeIdentifier">
				<xsl:choose>
					<xsl:when test="PromotionData/Elements/PurchaseCondition/IncludePaymentTypeIdentifier/Data/PaymentType != 'Any'">
						<Filter impl="com.ibm.commerce.marketing.promotion.condition.PaymentTypeFilter">
							<IncludePaymentType>
								<PaymentMethodName><xsl:value-of
select="PromotionData/Elements/PurchaseCondition/IncludePaymentTypeIdentifier/Data/PaymentType" />
								</PaymentMethodName>
							</IncludePaymentType>
						</Filter>
					</xsl:when>
				</xsl:choose>						
			</xsl:when>
		</xsl:choose>	
		<Filter impl="com.ibm.commerce.marketing.promotion.condition.ItemSortingFilter">
			<SortingMethod>PriceLowToHigh</SortingMethod>        	
		</Filter>								
	</FilterChain>
</Constraint>