I have the following xml
<?xml version="1.0" encoding="UTF-8"?>
<Results>
<form-type>orderform-A</form-type>
<data>
<form-data>
<field>
<name>productid-1</name>
<value>Yes</value>
</field>
<field>
<name>productid-3</name>
<value>Yes</value>
</field>
<field>
<name>productid-4</name>
<value>Yes</value>
</field>
</form-data>
</data>
</Results>
On orderform-A customer can order the following products
productid-4 if ordered along with productid-2 or productid-3 is offered for free. Note the order form will only list the products ordered.
Similarly I have the following order form which also allows customers to order multiple quantities of each product :
<?xml version="1.0" encoding="UTF-8"?>
<Results>
<form-type>orderform-B</form-type>
<data>
<form-data>
<field>
<name>productid-w</name>
<value>Yes</value>
</field>
<field>
<name>productid-w-qty</name>
<value>1</value>
</field>
<field>
<name>productid-x</name>
<value>Yes</value>
</field>
<field>
<name>productid-x-qty</name>
<value>1</value>
</field>
<field>
<name>productid-y</name>
<value>Yes</value>
</field>
<field>
<name>productid-y-qty</name>
<value>1</value>
</field>
</form-data>
</data>
</Results>
On orderform-B customer can order the following products
I want to calculate the total cost of each order so I've tried something as follows:
<xsl:param name="form-type">
<xsl:param name="total">0</xsl:param>
<xsl:template match="/">
<xsl:choose>
<xsl:when test="$form-type = 'orderform-A'">
<xsl:call-template name="orderform-A-total"/>
</xsl:when>
<xsl:when test="$form-type = 'orderform-B'">
<xsl:call-template name="orderform-B-total"/>
</xsl:when>
</xsl:choose>
</xsl:template>
<xsl:template name="orderform-A-total">
<xsl:if test="count(//Results/data/form-data/field[name='productid-1']/value) > 0">
<xsl:value-of select="$total + 5" />
</xsl:if>
<xsl:if test="count(//Results/data/form-data/field[name='productid-2']/value) > 0">
<xsl:value-of select="$total + 5" />
</xsl:if>
<xsl:if test="count(//Results/data/form-data/field[name='productid-3']/value) > 0">
<xsl:value-of select="$total + 5" />
</xsl:if>
<xsl:if test="(count(//Results/data/form-data/field[name='productid-4']/value > 0)">
<xsl:value-of select="$total + 5" />
</xsl:if>
<xsl:value-of select="$total" /></value>
</xsl:template>
<xsl:template name="orderform-B-total">
// TO DO
</xsl:template>
But this doesn't work. How do I calculate the total for the different types of order forms?
In your place I would probably do something like:
XSLT 2.0
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:variable name="pricelist">
<item id="productid-1">5</item>
<item id="productid-2">5</item>
<item id="productid-3">5</item>
<item id="productid-4">5</item>
</xsl:variable>
<xsl:key name="price" match="item" use="@id" />
<xsl:template match="/">
<total>
<xsl:apply-templates/>
</total>
</xsl:template>
<xsl:template match="Results[form-type='orderform-A']">
<xsl:variable name="charges">
<xsl:apply-templates select="data/form-data/field"/>
</xsl:variable>
<xsl:value-of select="sum($charges/charge)" />
</xsl:template>
<xsl:template match="field">
<charge>
<xsl:value-of select="key('price', name, $pricelist)"/>
</charge>
</xsl:template>
<xsl:template match="Results[form-type='orderform-B']">
<!-- TO DO -->
</xsl:template>
</xsl:stylesheet>
To implement a rule such as:
productid-4 if ordered along with productid-2 or productid-3 is offered for free
you can add an empty template like:
<xsl:template match="field[name='productid-4'][../field[name='productid-2' or name='productid-3']]"/>
Note that there is no need for a form-type
parameter when the input has a form-type
element.
To handle the orderform-B
variant, you could do:
<xsl:template match="Results[form-type='orderform-B']">
<xsl:variable name="charges">
<xsl:apply-templates select="data/form-data/field[value='Yes']" mode="B"/>
</xsl:variable>
<xsl:value-of select="sum($charges/charge)" />
</xsl:template>
<xsl:template match="field" mode="B">
<xsl:variable name="price" select="key('price', name, $pricelist)" />
<xsl:variable name="qty" select="following-sibling::field[1]/value" />
<charge>
<xsl:value-of select="$price * $qty"/>
</charge>
</xsl:template>
And, of course, you must also add the items to the $pricelist
variable.