[XSL-LIST Mailing List Archive Home] [By Thread] [By Date] [Recent Entries] [Reply To This Message]

Re: determine the number of payment methods and specif

Subject: Re: determine the number of payment methods and specify order depending on page type being viewed
From: Wendell Piez <wapiez@xxxxxxxxxxxxxxxx>
Date: Tue, 04 Nov 2008 10:26:42 -0500
Re:  determine the number of payment methods and specif
Caroline,

At 07:09 PM 11/3/2008, you wrote:
Sorry...first time in posting here...

No apology necessary ... just trying to help us help you --


ok, so here's an amended version of the XSL:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:html="http://www.w3.org/1999/xhtml">
...
<xsl:template name="checkOutProgressStep">
  <xsl:param name="label"/>
  <xsl:variable name="noOfNodes" select="count(/order/paymentMethods/*)" />

<xsl:choose>
<xsl:when test="$noOfNodes = '3'"><!-- check for 3 elements -->
<xsl:choose>
<xsl:when test="$label = 'directDebit'">
<li class="doubleLine current">Payment by <br/>Direct Debit</li>
<li class="doubleLine">Payment by <br/>Credit Card</li>
<li class="doubleLine">Payment by <br/>Invoice</li>
</xsl:when>


<xsl:when test="$label = 'creditCard'">
<li class="doubleLine completed">Payment by <br/>Direct Debit</li>
<li class="doubleLine current">Payment by <br/>Credit Card</li>
<li class="doubleLine">Payment by <br/>Invoice</li>
</xsl:when>


<xsl:when test="$label = 'invoice'">
<li class="doubleLine completed">Payment by <br/>Direct Debit</li>
<li class="doubleLine completed">Payment by <br/>Credit Card</li>
<li class="doubleLine current">Payment by <br/>Invoice</li>
</xsl:when>
</xsl:choose>
</xsl:when>


  </xsl:choose>
</xsl:template>
...
</xsl:stylesheet>

Thanks. This is much easier to see.


You'll notice that for the current payment method (specified in the xsl:when test="..."), the class "current" is added. If a payment method exists before the current one, then this will have a class "completed", whereas any subsequent to the current matching payment will have no extra class.

Right.


From your earlier email:

The XML file comes through as :
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="InvoiceForm.xslt"?>

<order>
   <!-- for navigation -->
   <paymentMethods>
       <!-- shopping cart had credit card and invoice payments;
credit card payment is already completed -->
       <creditCard />
        <invoice />
   </paymentMethods>
...
</order>

and


So, each page would have label set as
creditCard - for CC payment
directDebit - for DD payment
invoice - for invoice payment.

Within the XML, the paymentMethods area can have one, two or three
nodes available (no more or less).

The problem that I have (besides not knowing that much), is that if
all three payment methods are applicable, then they need to be in the
order:

DD payment
CC payment
I payment

DD payment should always be first, and I payment last.

If the label is set to creditCard (for example), then that indicates
the page is a Credit Card page.  If this is the case, then the class
applied to the relevant list item will be class="doubleLine current".
If there are 3 payment methods for the xml, then DD payment should
have a class set as class="doubleLine completed" and Invoice should be
class="doubleLine".

So not only do I need to determine the number of payment methods
present, but I need to specify a type of order to them, and apply the
relevant class, depending on the page type being viewed.

I'd actually suggest a shortcut to simplify this approach. What XSLT excels at above all is processing input data when it exists, and not when it doesn't, without extra work on the programmer's part. This may sound silly, but it's simply a consequence of the way XSLT is "input driven" -- and it's not true of all data processing technologies. A very normal way to do this in XSLT is:


<xsl:apply-templates/>

... which processes all the children of the context node (not including children that might have been given in the document, but weren't), placing the results in document order.

If you want to fix the order of the children of 'paymentMethods', you can do:

<xsl:template match="paymentMethods">
  <ul>
    <xsl:apply-templates select="directDebit"/>
    <xsl:apply-templates select="creditCard"/>
    <xsl:apply-templates select="invoice"/>
  </ul>
</xsl:template>

Notice: this template will fire when 'paymentMethods' is selected by an apply-templates somewhere (and so this template is matched), so the 'directDebit', 'creditCard' and 'invoice' elements selected will be the children of 'paymentMethods'. It would also work in a named template like yours, as long as the current node is still the 'paymentMethods'; if not, the path expressions can be adjusted.

Then it's a simple matter of writing templates that match these three elements that do the right thing. In this case, generate 'li' elements with the appropriate class attributes.

So:

<xsl:template match="directDebit">
  <li class="?">Payment by <br/>Direct Debit</li>
</xsl:template>

<xsl:template match="creditCard">
  <li class="?">Payment by <br/>Credit Card</li>
</xsl:template>

<xsl:template match="invoice">
  <li class="?">Payment by <br/>Invoice</li>
</xsl:template>

... notice I've punted on assigning the 'class' attributes here ... trying to illustrate things one step at a time.

Now it happens that the fact that you're generating the results in a fixed order actually simplifies things for you. Your 'class' attributes can each be one of three values, "doubleLine completed", "doubleLine current" and "doubleLine". But because the elements will come in order, these do not map arbitrarily. Actually it's something like this:

<xsl:template match="directDebit">
  <xsl:variable name="status">
    <xsl:choose>
      <xsl:when test="$label = 'directDebit'">current</xsl:when>
      <xsl:otherwise>completed</xsl:otherwise>
    </xsl:choose>
  </xsl:variable>
  <li class="doubleLine {$status}">Payment by <br/>Direct Debit</li>
</xsl:template>

<xsl:template match="creditCard">
  <xsl:variable name="status">
    <xsl:choose>
      <xsl:when test="$label = 'directDebit'>completed</xsl:when>
      <xsl:when test="$label = 'creditCard'>current</xsl:when>
      <xsl:otherwise/>
    </xsl:choose>
  </xsl:variable>
  <li class="doubleLine {$status}">Payment by <br/>Credit Card</li>
</xsl:template>

<xsl:template match="invoice">
  <xsl:variable name="status">
    <xsl:choose>
      <xsl:when test="$label = 'invoice'>current</xsl:when>
      <xsl:otherwise/>
    </xsl:choose>
  </xsl:variable>
  <li class="doubleLine {$status}">Payment by <br/>Invoice</li>
</xsl:template>

... I won't try to explain the logic of the assignment of values to $status in each case. You should examine and test it to be sure I'm right. (The logic assumes that only three values are possible.)

But it's worth noticing I use XSLT "attribute value syntax" (the { } syntax) to get this value into the li/@class attribute.

Cosmetically, if you don't like the extra space you get on the @class when $status has no value, you can write around that like this:

  <xsl:variable name="status">
    <xsl:if test="$label = 'directDebit'"> current</xsl:if>
  </xsl:variable>
  <li class="doubleLine{$status}">Payment by <br/>Direct Debit</li>

The other concern here is to make sure that $label is available as a global parameter or variable; you said it was set at run time, so I assume it is.

I think this handles your problem, except for one exception. What happens if $label is set to 'creditCard', say, but you have no 'creditCard' element? Currently, the stylesheet will generate:

<ul>
  <li class="doubleLine completed">Payment by <br/>Direct Debit</li>
  <li class="doubleLine">Payment by <br/>Invoice</li>
</ul>

If your system does not have a way of preventing this from happening, you need to think about what you want the stylesheet to do if (when) it does.

Finally -- notice that you don't need to test to see how many and which element children of 'paymentMethod' are present. Instead, this work is simply done by processing the input data: elements not present are not processed. :-) This is far more robust, and reflects the way XSLT is intended to work.

If you need to dive in and learn how to apply and match templates in order to get this going -- so much the better. You'll never understand XSLT without this capability. Template matching and the idea of "tree traversal" (context nodes, child elements, etc. etc.) are at the heart of the language.

Finally -- I have used XSLT 1.0 methods and idioms throughout. In XSLT 2.0, there are ways of making this more concise (and possibly opaque). But there's little point in doing this in XSLT 2.0 unless you can do it in XSLT 1.0 (which is arguably not true of all XSLT problems).

Please ask any followup questions for clarification.

Cheers,
Wendell



======================================================================
Wendell Piez                            mailto:wapiez@xxxxxxxxxxxxxxxx
Mulberry Technologies, Inc.                http://www.mulberrytech.com
17 West Jefferson Street                    Direct Phone: 301/315-9635
Suite 207                                          Phone: 301/315-9631
Rockville, MD  20850                                 Fax: 301/315-8285
----------------------------------------------------------------------
  Mulberry Technologies: A Consultancy Specializing in SGML and XML
======================================================================

Current Thread

PURCHASE STYLUS STUDIO ONLINE TODAY!

Purchasing Stylus Studio from our online shop is Easy, Secure and Value Priced!

Buy Stylus Studio Now

Download The World's Best XML IDE!

Accelerate XML development with our award-winning XML IDE - Download a free trial today!

Don't miss another message! Subscribe to this list today.
Email
First Name
Last Name
Company
Subscribe in XML format
RSS 2.0
Atom 0.3
Site Map | Privacy Policy | Terms of Use | Trademarks
Free Stylus Studio XML Training:
W3C Member
Stylus Studio® and DataDirect XQuery ™are products from DataDirect Technologies, is a registered trademark of Progress Software Corporation, in the U.S. and other countries. © 2004-2013 All Rights Reserved.