Jump to content

Using Templates As A Subroutine


Aussie Mike
 Share

Recommended Posts

I believe i can use templates as a form of sub-routine? I have a few fields that are going to need to display a value for periods.e.g. Monthly,Quarterly, semi-annual, annual, Bi-ennial. I have written the below which i could just re-use over but it is messy and ihave to do weeklys as well which will be a lot more options.I've tried tweaking a few different things from the web, but can't get any progress on any. I think the difficulty of having to worry about the main and sub routine makes it hard for me to use my one line of code at a time process :-)Tutorial just introduces the very basic :-(Looking to make a monthly and weekly routine i believe i can call on both and it will resolve on which one applies. CheersXML.................................................<calculationPeriodFrequency> <periodMultiplier>3</periodMultiplier> <period>Monthly</period> <rollConvention>None</rollConvention> </calculationPeriodFrequency>XSLT............................................<xsl:choose> <xsl:when test="//calculationPeriodFrequency/period='Term'">No compound</xsl:when> <xsl:when test="//calculationPeriodFrequency/period='Year'">A</xsl:when> <xsl:when test="//calculationPeriodFrequency/period='Monthly'and//calculationPeriodFrequency/periodMultiplier='1'">M</xsl:when> <xsl:when test="//calculationPeriodFrequency/period='Monthly'and//calculationPeriodFrequency/periodMultiplier='3'">Q</xsl:when> <xsl:when test="//calculationPeriodFrequency/period='Monthly'and//calculationPeriodFrequency/periodMultiplier='6'">S</xsl:when> <xsl:otherwise> </xsl:otherwise></xsl:choose>...............................................This is an example of one i tried to tweak...but i have literally shoe horned it from somewhere else and don't know how to introduce it or syntax it properly<!-- Convert compounding --> <xsl:template name="comp_mth”> <xsl:param name='number'/> <xsl:choose> <xsl:when test=“$number=‘1’”>Monthly</xsl:when> <xsl:when test=“$number=‘3’“>Quarterly</xsl:when> <xsl:otherwise>??</xsl:otherwise> </xsl:choose> </xsl:template>

Edited by Aussie Mike
Link to comment
Share on other sites

Perhaps you're calling it wrong? Templates can be named or matched.Matched templates are activated with "xsl:apply-templates" and get executd when a certain descendant matches the pattern in the match attribute. All descendants get checks against all templates in your XSLT, so a template could be executed zero, one or several times, depending on the XML structure. This is especially useful for non-trivial XMLs with structures that can't be easily guessed in advance (like XHTML for example).Named templates are activated with "xsl:call-template" and get executed exactly once, only when called. Useful for repeaded pieces of XSLT, making it closer to the "subroutine" you're describing.Either way, upon activating a template, you can pass parameters to it to affect it's behaviour.With all that said, since you have:

<xsl:template name="comp_mth"><xsl:param name='number'/><xsl:choose><xsl:when test="$number='1'">Monthly</xsl:when><xsl:when test="$number='3'">Quarterly</xsl:when><xsl:otherwise>??</xsl:otherwise></xsl:choose></xsl:template>

you should be calling it like:

<xsl:call-template name="comp_mth"><xsl:with-param name="number" select="'1'"/></xsl:call-template>

Edited by boen_robot
Link to comment
Share on other sites

Cheers boen that really helped me with the calling and syntax i had brick-walled it yesterday and everything i looked at looked like "<'/"'>'/<"'>">/'"<''". :-) With your help I have made some real good advancement this morning on what i was after as a final result. Probably wasn't that clear on it as just wanted to get it started.Looking now at making it more generic to pull preiod and multiplier values from different paths and use the same table. Hopefully will be back here shortly to post a positive result.Thanks againXML.................................<calculationPeriodFrequency> <periodMultiplier>2</periodMultiplier> <period>Week</period> <rollConvention>None</rollConvention> </calculationPeriodFrequency>RESULT.......................................<test>Bi-Weekly</test>XML.................................................alternative values<calculationPeriodFrequency> <periodMultiplier>6</periodMultiplier> <period>Month</period> <rollConvention>None</rollConvention> </calculationPeriodFrequency>NEW RESULT..................................................<test>Semi-Annual</test>XSL................................................................................<?xml version='1.0'?><xsl:stylesheet xmlns:xsl='http://www.w3.org/1999/XSL/Transform' version='1.0'><xsl:output method="xml" indent="yes"/> <xsl:output omit-xml-declaration='yes'/><xsl:template match="/"> <test><xsl:call-template name="term_type"></xsl:call-template></test></xsl:template><!-- Determines wether to call Monthly (comp_mth), or Weekly (comp_wk) template --> <xsl:template name="term_type"> <xsl:variable name="term"> <xsl:value-of select="//calculationPeriodFrequency/period"/> </xsl:variable> <xsl:choose> <xsl:when test='$term="Month"'> <xsl:call-template name="comp_mth"> <xsl:with-param name="number"><xsl:value-of select="//calculationPeriodFrequency/periodMultiplier"/></xsl:with-param> </xsl:call-template> </xsl:when> <xsl:otherwise> <xsl:call-template name="comp_wk"> <xsl:with-param name="number"><xsl:value-of select="//calculationPeriodFrequency/periodMultiplier"/></xsl:with-param> </xsl:call-template> </xsl:otherwise> </xsl:choose> </xsl:template><!-- Converts number of months into a frequency --><xsl:template name="comp_mth"><xsl:param name='number'/><xsl:choose><xsl:when test="$number='1'">Monthly</xsl:when><xsl:when test="$number='3'">Quarterly</xsl:when><xsl:when test="$number='6'">Semi-Annual</xsl:when><xsl:otherwise>??</xsl:otherwise></xsl:choose></xsl:template><!-- Converts number of weeks into a frequency --><xsl:template name="comp_wk"><xsl:param name='number'/><xsl:choose><xsl:when test="$number='1'">Weekly</xsl:when><xsl:when test="$number='2'">Bi-Weekly</xsl:when><xsl:when test="$number='13'">13weeks</xsl:when><xsl:otherwise>??</xsl:otherwise></xsl:choose></xsl:template></xsl:stylesheet>

Link to comment
Share on other sites

Ok so pretty happy with what i have. Next stage is that there isn't just one frequency there are 3 or 4...possibly 8 for a Non deliverable X-ccy dual tenor swap.<tenorFrequency> <periodMultiplier>6</periodMultiplier> <period>Month</period> <rollConvention>None</rollConvention> </tenorFrequency> <paymentFrequency> <periodMultiplier>1</periodMultiplier> <period>Month</period> <rollConvention>None</rollConvention> </paymentFrequency>Anyway i want to use the same templates to resolve all the frequencies. Have tried moving the variable definition outside of the template and in the individual tags. <calc_freq><xsl:call-template name="term_type"> <xsl:variable name="term"> <xsl:value-of select="//calculationPeriodFrequency/period"/> .....i could insert a different path for each one </xsl:variable></xsl:call-template></calc_freq>i have also tried reducing the path in the term_type template to just //periodMultiplier and then define the partial path in the tag e.g. //calculationPeriodFrequency or //paymentFrequency this will retrieve all tags under this path anddisplay them then carry on with the template call.Unfortunately i haven't been able to get any ideas to work. Not sure if it's not the way to do it or the syntax.Cheers

Link to comment
Share on other sites

The only thing xsl:call-template or xsl:apply-templates may contain is xsl:with-param element. No new variables or parameters. You could have:

<calc_freq><xsl:call-template name="term_type"><xsl:with-param name="term"><xsl:value-of select="//calculationPeriodFrequency/period"/></xsl:with-param></xsl:call-template></calc_freq>

and in the template itself:

<xsl:template name="term_type"><xsl:param name="term"><xsl:value-of select="//calculationPeriodFrequency/period"/></xsl:param><xsl:choose><xsl:when test='$term="Month"'><xsl:call-template name="comp_mth"><xsl:with-param name="number"><xsl:value-of select="//calculationPeriodFrequency/periodMultiplier"/></xsl:with-param></xsl:call-template></xsl:when><xsl:otherwise><xsl:call-template name="comp_wk"><xsl:with-param name="number"><xsl:value-of select="//calculationPeriodFrequency/periodMultiplier"/></xsl:with-param></xsl:call-template></xsl:otherwise></xsl:choose></xsl:template>
The two main differences between variables and parameters are that parameters can be influenced from the outside, and can only be placed as childs of xsl:stylesheet or xsl:template. Variables can't be influenced from the outside, but can be placed anywhere in the XSLT document. Edited by boen_robot
Link to comment
Share on other sites

Thanks again.I've tried similar, but it falls over when i want to remove the specific paths in the template.I need to be able to remove the bold in thetemplate and reference relative to the higher path in the initial template call.<xsl:template name="term_type"><xsl:param name="term"><xsl:value-of select="//calculationPeriodFrequency/period"/></xsl:param><xsl:choose><xsl:when test='$term="Month"'><xsl:call-template name="comp_mth"><xsl:with-param name="number"><xsl:value-of select="//calculationPeriodFrequency/periodMultiplier"/></xsl:with-param></xsl:call-template></xsl:when><xsl:otherwise><xsl:call-template name="comp_wk"><xsl:with-param name="number"><xsl:value-of select="//calculationPeriodFrequency/periodMultiplier"/></xsl:with-param></xsl:call-template></xsl:otherwise></xsl:choose></xsl:template>So when the initial call is (below) it checks //calculationPeriodFrequency/period against //calculationPeriodFrequency/periodMultiplier<calc_freq><xsl:call-template name="term_type"><xsl:with-param name="term"><xsl:value-of select="//calculationPeriodFrequency/period"/></xsl:with-param></xsl:call-template></calc_freq>However when the initial call is (below) it checks //paymentFrequency/period against //paymentFrequency/periodMultiplier<pay_freq><xsl:call-template name="term_type"><xsl:with-param name="term"><xsl:value-of select="//paymentFrequency/period"/></xsl:with-param></xsl:call-template></pay_freq>Can i do this with the one set of templates..?

Link to comment
Share on other sites

Have you considered using matched templates instead?You may have one template for every "calculationPeriodFrequency" element, and execute the rest based on it, like:

<xsl:template match="calculationPeriodFrequency"><xsl:param name="term"><xsl:value-of select="period"/></xsl:param><xsl:choose><xsl:when test='$term="Month"'><xsl:call-template name="comp_mth"><xsl:with-param name="number"><xsl:value-of select="periodMultiplier"/></xsl:with-param></xsl:call-template></xsl:when><xsl:otherwise><xsl:call-template name="comp_wk"><xsl:with-param name="number"><xsl:value-of select="periodMultiplier"/></xsl:with-param></xsl:call-template></xsl:otherwise></xsl:choose></xsl:template>

And to use this, you'd have to do this at some other point:

<xsl:apply-templates/>

prefferably, the root template, like:

<xsl:template match="/"><xsl:apply-templates/></xsl:template>

Take a step back, and try to find out how match templates really work out. They require a shift in the mindset, but once you grasp them, XSLT suddenly becomes much more powerful and easy.

Edited by boen_robot
Link to comment
Share on other sites

O.k. thought i was getting somewhere with the line by line unfortunately.... :-(This is my latest attempt. I need the <xsl:value-of select> to be in the original call so it can be re-used more fluidly.This does not work as error states.....xsl:with-param is not allowed in this position in the stylesheet! <xsl:template match="/"> <calc_freq><xsl:call-template name="term_type"> <xsl:with-param name="term"> <xsl:value-of select="//calculationPeriodFrequency/period"/> <xsl:with-param name="number"> <xsl:value-of select="//calculationPeriodFrequency/periodMultiplier"/> </xsl:with-param></xsl:call-template></calc_freq><pay_freq><xsl:call-template name="term_type"> <xsl:with-param name="term"> <xsl:value-of select="//paymentFrequency/period"/> <xsl:with-param name="number"> <xsl:value-of select="//paymentFrequency/periodMultiplier"/> </xsl:with-param></xsl:call-template></pay_freq></xsl:template><!-- Determines wether to call Monthly (comp_mth), or Weekly (comp_wk) template --> <xsl:template name="term_type"> <xsl:param name="term"> </xsl:param> <xsl:choose> <xsl:when test='$term="Month"'> <xsl:call-template name="comp_mth"> <xsl:with-param name="number">></xsl:with-param> </xsl:call-template> </xsl:when> <xsl:otherwise> <xsl:call-template name="comp_wk"> <xsl:with-param name="number"></xsl:with-param> </xsl:call-template> </xsl:otherwise> </xsl:choose> </xsl:template><!-- Converts number of months into a frequency --><xsl:template name="comp_mth"><xsl:param name='number'/><xsl:choose><xsl:when test="$number='1'">Monthly</xsl:when><xsl:when test="$number='3'">Quarterly</xsl:when><xsl:when test="$number='6'">Semi-Annual</xsl:when><xsl:otherwise>??</xsl:otherwise></xsl:choose></xsl:template><!-- Converts number of weeks into a frequency --><xsl:template name="comp_wk"><xsl:param name='number'/><xsl:choose><xsl:when test="$number='1'">Weekly</xsl:when><xsl:when test="$number='2'">Bi-Weekly</xsl:when><xsl:when test="$number='13'">13weeks</xsl:when><xsl:otherwise>??</xsl:otherwise></xsl:choose></xsl:template></xsl:stylesheet>Interestingly when i applied this procedure to just the first param it resolved, but this needs to apply to the periodmultiplier as well.Dinner with the rellies...the quest shall continue tomorrow but any advice welcomedCheers

Link to comment
Share on other sites

You have forgotten to close your first xsl:with-param element. Therefore, the second one appears as its direct child... and xsl:with-param can't be a direct child of another xsl:with-param.

<xsl:call-template name="term_type"><xsl:with-param name="term"><xsl:value-of select="//calculationPeriodFrequency/period"/><xsl:with-param name="number">
Should be
<xsl:call-template name="term_type"><xsl:with-param name="term"><xsl:value-of select="//calculationPeriodFrequency/period"/></xsl:with-param><xsl:with-param name="number">
I'm guessing the late hours is affecting you. Edited by boen_robot
Link to comment
Share on other sites

CheersHave tried both methods one </param> end with two params and ending each one with a </param>. Same issue...I think it doesn't like it because the second param is for another template.Tried having "number" as a variable not param tried various locations in the <test> field and outside in main root as a "global"..? Unfortunatley no go<test><xsl:call-template name="term_type"> <xsl:with-param name="term"> <xsl:value-of select="//calculationPeriodFrequency/period"/> </xsl:with-param> <xsl:with-param name="number"> <xsl:value-of select="//calculationPeriodFrequency/periodMultiplier"/> </xsl:with-param> </xsl:call-template></test></xsl:template><!-- Determines wether to call Monthly (comp_mth), or Weekly (comp_wk) template --> <xsl:template name="term_type"> <xsl:param name="term"> </xsl:param> <xsl:choose> <xsl:when test='$term="Month"'> <xsl:call-template name="comp_mth"> <xsl:param name="number"></xsl:param> </xsl:call-template> </xsl:when> <xsl:otherwise> <xsl:call-template name="comp_wk"> <xsl:param name="number"></xsl:param> </xsl:call-template> </xsl:otherwise> </xsl:choose> </xsl:template>My latest venture involves concat.<test2> <xsl:variable name='startpath'> <xsl:value-of select="'//calculationPeriodFrequency'"/> </xsl:variable><xsl:call-template name="term_type"> <xsl:with-param name="term"> <xsl:value-of select="concat($startpath,'/period')"/> </xsl:with-param></xsl:call-template></test2>Doesn't work :-(<xsl:value-of select="concat($startpath,'/periodMultiplier')"/> outputs <test2>//calculationPeriodFrequency/periodMultiplier</test2>but i can't get it to accept it as the path for <xsl: value-of select> ....??? was hoping the transformer would just see <xsl:value-of select="//calculationPeriodFrequency/periodMultiplier"/>By using this $startpath i'm hoping that for each <tag> i can redefine what start path means then apply via "concat" as part of the path to retrieve the value.Any ideas?Cheers

Link to comment
Share on other sites

The "select" attribute takes the value of the expression as the value of the parameter. It doesn't evaluate it as an XPath expression to take the value from.I still think you need to look into matched templates. There are certain XSLT extensions that can do what you want, but by definition, they differ from one XSLT processor to another, and should not be relied upon. Matched templates on the other hand are part of the XSLT standard, and have the kind of power you need.

Link to comment
Share on other sites

Cheers I'll definately take a look. For now i'm going with a slightly less fancy solution. I've basically ditched the first template and just inserted it in the main body. I know i'll have to repeat this for each one, but the majority of the code will end up being in the other two comp_wk and comp_mth tables. I have 20+ different frequency outputs to stick in them.Cheers again for your help on this you really do know your stuff!

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

×
×
  • Create New...