• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 938
  • Last Modified:

What is <xsl:apply-templates/> and <xsl:template match="@*|node()">

Hello - I am trying to understand a few concepts in XSLT. For e.g., what does this snippet of code do?

<xsl:template match="@*|node()">
      <xsl:apply-templates/>
</xsl:template>

Can someone please give me a noob's take on that. Also, I am trying to extract First, Last names and email address from the xml below. I am also attaching the xslt that I have

Here's my xml

<Envelope>
    <Body>
        <NewMember>
            <CustID>1</CustID>
            <CustMisc>
                <BirthDate>1979-04-07</BirthDate>
                <Gender>Female</Gender>
                <CustFirstName>Chaitanya</CustFirstName>
                <CustLastName>Allam</CustLastName>
            </CustMisc>
            <CustPhone>
                <AreaCode>972</AreaCode>
                <Number>415 4672</Number>
            </CustPhone>
            <EMailAddress Location="Home">
                <PersonalEMailAddr>Chaitu@yahoo.com</PersonalEMailAddr>
				<WorkEMailAddr>Chaitu@yahoo.com</WorkEMailAddr>
            </EMailAddress>
            <CustPermanentAddress>
                <StreetNo1>1229 </StreetNo1>
                <StreetNo2>Deerfield Parkway</StreetNo2>
                <City>Buffalo Grove</City>
                <State>IL</State>
                <ZipCode>60089</ZipCode>
                <Country>USA</Country>
            </CustPermanentAddress>
            <CustWorkAddress>
                <StreetNo1>1229</StreetNo1>
                <StreetNo2>Deerfield Parkway</StreetNo2>
                <City>Buffalo Grove</City>
                <State>IL</State>
                <ZipCode>60089</ZipCode>
                <Country>USA</Country>
            </CustWorkAddress>	
        </NewMember>


		<NewMember>
            <CustID>2</CustID>
            <CustMisc>
                <BirthDate>1980-05-03</BirthDate>
                <Gender>Male</Gender>
                <CustFirstName>Balaji</CustFirstName>
                <CustLastName>Allam</CustLastName>
            </CustMisc>
            <CustPhone>
                <AreaCode>972</AreaCode>
                <Number>415 4672</Number>
            </CustPhone>
            <EMailAddress Location="Work">
                <EMailAddr>balaji.allam@yahoo.com</EMailAddr>
            </EMailAddress>
            <CustPermanentAddress>
                <StreetNo1>1335 </StreetNo1>
                <StreetNo2>Deerfield Parkway</StreetNo2>
                <City>Buffalo Grove</City>
                <State>IL</State>
                <ZipCode>60089</ZipCode>
                <Country>USA</Country>
            </CustPermanentAddress>
            <CustWorkAddress>
                <StreetNo1>1229</StreetNo1>
                <StreetNo2>Deerfield Parkway</StreetNo2>
                <City>Buffalo Grove</City>
                <State>IL</State>
                <ZipCode>60089</ZipCode>
                <Country>USA</Country>
            </CustWorkAddress>
       </NewMember>
    </Body>
</Envelope>

Open in new window


The below is my XSLT:

<?xml version='1.0'?>
<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 

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


<xsl:template match="Envelope/Body/NewMember/CustMisc"> 
	<xsl:apply-templates select="CustFirstName"/>
	<xsl:apply-templates select="CustLastName"/>	 
	<br/>
</xsl:template>


<xsl:template match="Envelope/Body/NewMember/EMailAddress/PersonalEMailAddr"> 
	<xsl:apply-templates select="EMailAddr"/>	 
	<br/><br/>
</xsl:template>


<xsl:template match="CustFirstName"> 
  First Name:  <xsl:value-of select="."/>  
  <br/>
</xsl:template> 

<xsl:template match="CustLastName"> 
  Last Name:  <xsl:value-of select="."/>  
</xsl:template> 

<xsl:template match="EMailAddr">  
  	EMailAddress:  <xsl:value-of select="."/>  
</xsl:template> 

<xsl:template match="@*|node()"> 
	<xsl:apply-templates/>
</xsl:template> 


</xsl:stylesheet>

Open in new window


Here's the result I am getting right now:

First Name: Chaitanya
Last Name: Allam


First Name: Balaji
Last Name: Allam
EMailAddress: balaji.allam@yahoo.com
0
Jammerules
Asked:
Jammerules
  • 6
  • 3
1 Solution
 
zc2Commented:
In XSLT there is a such thing as implicit "default template". It prints the text content of a node and applies all the matched template for the children node.
This template you're asking about replaces that default template by itself. It does almost the same (applies the children nodes), but does not prints the node's text content.
0
 
Geert BormansCommented:
Hi,

XSLT is a rule based programming language. You need to understand that its most common mode of operation is hierarchical. The processing follows the structure of the data. That is a whole lot different than procedural programming
An XSLT stylesheet consists of a number of templates with a match attribute
The match attribute is the "rule", it specifies the node (through an XPath expression) for which this template is active. Templates are in a sense independent of each other and are place next to each-other (at the same level).
<xsl:apply-templates/> is the mechanism that is used to push nodes to the templates. The nodes go looking for the template that describes the node the most precise, and that specific template will than operate on the node.
xsl:apply-templates without a select attribute will send the childnodes of the current context out (current context is the current node the template is working on). With a select attribute you can be more precise

eg.

<foo>
  <bar>test</bar>
</foo>

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

will be the starting point of your stylesheet. By default an XSLT stylesheet starts at the document node "/" and the XSLT processing will look for this template
the apply-templates will push the foo root node (child of "/") to the templates

maybe there is a template like this
<xsl:template match="foo">
<xsl:apply-templates/>
</xsl:template>
the foo node will trigger this template
(so the processing jumps from inside the first template to this second template)
inside the foo template the child nodes are again pushed to the templates for finding the most precise template

<xsl:template match="foo/bar">
<xsl:value-of select="."/>
</xsl:template>
<xsl:template match="bar">
...
</xsl:template>

the bar node will pick the first template because that one is more precisely describing the bar node (having a foo parent)

I hope this helps
0
 
Geert BormansCommented:
<xsl:template match="@*|node()">
      <xsl:apply-templates/>
</xsl:template>

this one is a template that will simply push the children of any node to the templates
note that this template will only be active as a fallback since most of your nodes will be picked up by a specific template of their own
0
Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
JammerulesAuthor Commented:
OK. This is a little overwhelming. Let's see if you can cut this sucker in parts!

So, I understand that the control actually passes hierarchically down. So, in my example XML,XSLT above, the controls starts at "/" which is like the beginning of time and then I am saying apply templates ... like this:

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

Open in new window


So, when the control reaches       <xsl:apply-templates/>,  what does it actually do? Is it going to execute some built-in code like zc2 mentioned? Assuming there was a default code that it executed. Then what? Does the control go to here..
<xsl:template match="Envelope/Body/NewMember/CustMisc"> 
	<xsl:apply-templates select="CustFirstName"/>
	<xsl:apply-templates select="CustLastName"/>	 
	<br/>
</xsl:template>

Open in new window


If it does, am I to understand that I have XPATH'd the control to apply the templates (CustFirstName and CustLastName) for the children of CustMisc. Am I correct?


Assuming I am correct so far (which I doubt :) ), now what does this part of code do?
<xsl:template match="CustFirstName"> 
  First Name:  <xsl:value-of select="."/>  
  <br/>
</xsl:template> 

Open in new window


So, assuming the context of the XPATH is (from my example xml above):

<BirthDate>1979-04-07</BirthDate>
<Gender>Female</Gender>
<CustFirstName>Chaitanya</CustFirstName>
<CustLastName>Allam</CustLastName>

Is it going to print all the above child node values?

I am sorry if my questions are so granular, but I have looked at most of the resources online and it is either I don't understand them or they are not detailed enough.
0
 
Geert BormansCommented:
the controls starts at "/" which is like the beginning of time

Yes

So, when the control reaches       <xsl:apply-templates/>,  what does it actually do? Is it going to execute some built-in code like zc2 mentioned? Assuming there was a default code that it executed. Then what? Does the control go to here..

Yes and no....
apply-templates will push all child nodes to the templates for evaluation
(that is basically the root element in this example)
If there is no matching template, a built-in template will be used
The root of your XML is <Envelope>
If you have no template for match="Envelope", or match="*" (less specific) or match="node()" (less specific).... the node will be picked up by the built-in for elements,
which equals

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

Open in new window


But in your stylesheet, there is the code on line 38
<xsl:template match="@*|node()"> 
	<xsl:apply-templates/>
</xsl:template> 

Open in new window

which will be the last resort in this particular stylesheet, and you will never hit the built-in
0
 
Geert BormansCommented:
<xsl:template match="Envelope/Body/NewMember/CustMisc"> 
	<xsl:apply-templates select="CustFirstName"/>
	<xsl:apply-templates select="CustLastName"/>	 
	<br/>
</xsl:template>

Open in new window


Is your template for CustMisc
It will be active on the CustMisc element (assuming that node will be pushed out at some point)
It is pretty specific, because it specifies the full path to CustMisc
Once there it, first pushes out the CustFirstName node(s) that are child of the current CustMisc
and then it pushes all CustLastName that are child of the current CustMisc

The @select is relative to the current context

Note that you are specific here about which nodes you push out, the others will not be processed.

So you aren't too far off

And you are pretty right about the quality of the average online resource on XSLT, explaining this mechanism ... pretty crappy :-)

the CustFirstName node will be picked up by the next template
which outputs some text and the string value of the current context
0
 
Geert BormansCommented:
It is by the way an interesting experience to download a tool such as www.oxygenxml.com
run the XSLT in that tool and put a debug stop in every template.
That way you can follow the execution of the program

as for books, this one tells it all in a very consumable way
http://shop.oreilly.com/product/9780596000530.do
0
 
JammerulesAuthor Commented:
EXCELLENT! Thanks so much for such detailed explanation. Yes, I will try to download OxygenXML but for now, I am using Stylus Studio XML for debugging...I am struggling but anyhow I think I am able to wrap my head around it a little bit.
0
 
JammerulesAuthor Commented:
Also, thanks zc2 for your quick response!
0
 
Geert BormansCommented:
welcome,

no need to download Oxygen if you are using Stylus.
They are very similar in some aspects (I use both)

You can actually put breakpoints in your code in Stylus too, so you can follow the execution
(Debug/Breakpoints)
0

Featured Post

Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

  • 6
  • 3
Tackle projects and never again get stuck behind a technical roadblock.
Join Now