Welcome back to the XCS Data Mapper XSLT data transformation tutorial series. In this 10 minute tutorial we’ll look at the use of the XSL template family of tags and how they are used to implement modularity and declarative control flow. This tutorial builds on concepts discussed in the XSLT Flow Control & Basic XPaths lesson. By the end of this episode you’ll be able to declare a new template to match a given XPath, call unnamed templates with XSL applied templates, create a name template to achieve modularity, and pass parameters to a name template.
We’ll begin where we finished off with the XSLT Flow Control & Basic XPath lesson. Here we developed a style sheet that would output information for every Fish that was in the same Family as the Pilotfish.
Now, let’s use a template rather than a for-each to display all of the various Fish in our input FishXML document. To do this, first we’ll use the Template tab underneath the XSLT Structures tab. To add a new template to the mapping we’ll grab the template tool and drop it onto the stylesheet node. are nodes which have attributes and child nodes. generally they pretty interchangeable. using a good analogy you can think of it this way: node is like fruit an element apple. apple kind class=”lexicon-term”>node.
A new blue template Node will appear.
Since we want this template to appear each time we see a Fish element coming in, we’ll drag the Fish element on top of the template.
Each time we see a Fish element we’ll want to generate what we’re currently generating underneath the for-each, that is this ListItem.
We can now just move this. We can drag the ListItem from underneath the for-each onto our new Fish template.
Note that if we run this now in Testing Mode we’ll have no Output.
This is because when we first execute a transformation, the context node is set to FishXML. The FishXML template that we began with is the only thing that matches and all it does now is output a SimpleFishList with nothing in the body.
In order to tell the XSLT Processor to apply all templates relevant to the current context node, we’ll need to use the apply-templates call. Underneath the XSLT Structures Template tab, we’ll drag the apply-templates node on top of the SimpleFishList.
Also, to clean things up, we’ll delete our variable and for-each definitions.
Now, once we’ve matched on FishXML, our context is FishXML. We’ll output our SimpleFishList tag and then apply templates relevant to the current context. Now, since there are Fish that are children of FishXML, our Fish template should be executed.
When we execute our transformation, again we see our full SimpleFishList.
However, you’ll recall that in the previous lesson we did some filtering on this FishList. For instance, we were looking for Fish that we either in the same Family or the same Order as the Pilotfish. We can take these same types of conditions that we used with the for-each to limit the type of Fish that will match this Fish template. For instance, let’s look for those Fish that are in the same Family as the Pilotfish. We’ll copy the condition from our choose clause, double click the Fish node, and enter in an XPath predicate using a square bracket, and pasting the same condition that we used in the when underneath the choose.
We’ll hit Enter. Then return to the Testing Mode and rerun the transform. We’ll see that immediately under the SimpleFishList is a bunch of plain text. What’s happened here is that we have a number of different child elements of FishXML that didn’t match anything so they were output in this fashion.
Note that those Families that were in the same Family as the Pilotfish were output correctly.
So what we need to do is to also implement a catch all template that will catch those Fish that don’t match our condition. To do that we’ll return back to the Mapping node and drag another template onto our stylesheet.
This one will simply match any Fish and won’t be associated with any child element output.
You can see now that we are presented
with a SimpleFishList with only those Fish that are in the same Family as the Pilotfish.
Note that the more specific template, the one with the XPath predicate, takes precedence over the less specific Fish template.
Now let’s assume that we want to create a names template. This is more akin to a functional call in traditional programming languages. We’ll drag the name template tool on top of the stylesheet.
You’ll see that these templates have a name as opposed to a select statement.
Double click the name attribute and we’ll call it outputFish.
We now have a name template called outputFish. Let’s have it do the work of outputting the ListItem representing the Fish. To accomplish this, what we’ll first do is Copy this mapping component onto our new outputFish template.
Next, we’ll want to replace what we’re doing here. When we add a new Named Template to the mapping it will appear in the Named Template Calls pallet entry. We can now drag our new template call outputFish onto our Fish template.
And we will delete our existing ListItem. We’ll see now that when the Fish template executes it will call the name template outputFish and do everything it was doing before.
Returning to Testing Mode we can see that this is exactly the case; we’re still outputting all of the Fish that are in the same Family as the Pilotfish.
Now, when we call a template with no parameters, the context of the template that we call will be the same as where we called it from. However, in many cases it’s useful to pass parameters into a function. So, rather than referring to our Fish, our current context as we’ve done here currently, assuming that the Fish is the current context, let’s pass the Fish instance in as a parameter.
Returning back to the XSLT Structures tab, and looking at the Variable sub-tab, we can see that we have param and with-param tools. To define a parameter for a template drag the param tool onto the template.
We give the parameter a name and a default value. Let’s call the name f for Fish and give it the default value of the current node (.).
Now we can go through and update the XPaths to reference our variable as opposed to the current context. As learned in the previous lesson, the syntax for referencing a variable is to use the $ preceding the variable name. Do this in two different spots.
When doing this type of replacement it can be useful to work in XSLT view.
Executing our template again, we should see the same results. Now, you’ll note that we did not pass a Fish into this template. But because we defaulted to the current node, everything worked.
Now, if we were to default to the parent node (..)
Our values should all be empty. This is because our context is now the FishXML instead of the Fish.
Now, to explicitly pass the correct parameter into the function, we add the with-param tag to the template call by dragging the with-param tool onto the call-template.
We need to match the name with the name of the parameter in our name template.
And we can provide a value. Let’s say we don’t want to output the current Fish, but we always want to output the Pilotfish, we can enter an XPath such as ../Fish[CommonName = ‘Pilotfish’].
Returning to the Testing tab and executing we’ll see that this name template is executed repeatedly, but each time it’s passed the Pilotfish.
Returning to the Mapping tree, if we change this instead to the current node.
We’ll again get the same results.
That’s all there is to it. We’ve seen how the XSL template, XSL apply-template, XSL call-template, XSL param, and XSL with-param tags are used to implement modularity and declarative control.