We help IT Professionals succeed at work.

What does this syntax mean?

Totally new to XSL/XSLT - trying to decipher some existing code. I would like an English-language explanation of what each of the following does. What I don't know is the syntax with the square brackets and colons - I'd like to know specifically what that is doing. Thanks.

<xsl:template match="Item[parent::MenuDataResult">

<xsl:template match="Item[child::Menu | ItemType='Submenu']">

<xsl:template match="@*|node()"



Comment
Watch Question

<xsl:template match="Item[parent::MenuDataResult]">
this template will process only "Item" element if it a child of MenuDataResult element

<xsl:template match="Item[child::Menu | ItemType='Submenu']">
process "Item" element only if it has either a child "Menu" or a child "ItemType" with the text value 'Submenu' inside.

<xsl:template match="@*|node()"
process either current element's attributes or subnodes.
Information Architect
Top Expert 2006
Commented:
Let's first get some of the basics out

using this XML
<root>
    <a>test1</a>
    <a>test2</a>
</root>

let's look at this stylesheet

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    version="1.0">
   
    <xsl:template match="/">
        <html>
            <body>
                <xsl:apply-templates/>
            </body>
        </html>
    </xsl:template>
   
    <xsl:template match="root">
        <ul>
            <xsl:apply-templates/>
        </ul>
    </xsl:template>
   
    <xsl:template match="a">
        <li><xsl:value-of select="."/></li>
    </xsl:template>
   
</xsl:stylesheet>

You see there are different template elements in this stylesheet
Well, when starting the execution, this template will be active
<xsl:template match="/"> (that is the template for processing the root)
and the actions in it will be executed.
There is some html tag construction and then you see <xsl:apply-templates/>

apply-templates pushes the child nodes for evaluation by the templates
There is a <root> element as a child of the document
so the processor looks for a template with a match attribute matching the pattern of the nood
in this case there is a template with a match="root", which perfectly fits the <root> element
So at that point the "actions" in this template are executed
There is a <ul> construction and then again you see the apply-templates
The child nodes will be pushed out again...

There are two <a> elements pushed out for evaluation by the template matches
and there is template match="a" which will pick them up (nearest match wins)
so that template willl be executed two times (once for each <a> element
That is where the <li> get constructed

You can see that there is some hierarchcal execution of the XSLT processing
after finishing with the a nodes, the processor actually returns to the continuing steps in the <root> template
(the part after apply-templates)

the values of the match attribute are XPath expressions
and you can be as specific as you want (the most detail, nearest match wins)

<xsl:template match="Item[parent::MenuDataResult">
Will catch the Item elements that have a parent MenuDataResult
Note: it is much better to chage that into
<xsl:template match="MenuDataResult/Item">
which has the same effect, but cheaper


<xsl:template match="Item[child::Menu | ItemType='Submenu']">
Will catch the Item elements that have a child Menu element or an ItemType element that has the string value 'Submenu'

<xsl:template match="@*|node()"
Is a catch all template, for all attributes (@*) and all element, comment, processing-instruction and text nodes)
Since the most detailed, nearest match wins, this template will catch all elements,
but not those that have a more detailed description in a match attribute,
such as the Item elements mentioned earlier

I hope this makes sense

cheers

Geert
Gertone (Geert Bormans)Information Architect
Top Expert 2006

Commented:
Other than the background I thought would be usefull for you, zc2's answer covers it all

There is a little flaw in his answer though

> <xsl:template match="@*|node()"
> process either current element's attributes or subnodes.

It is not necessarily current elements attributes or subnodes,
this template processes any attribute or any node
This makes no difference in the example I worked out,
but you should know that you can be selective in an apply-templates
<xsl:apply-templates select="//a"/>
will push out all teh a elements in the document, and they would get caught by
<xsl:template match="node()"/>
if there would not be a
<xsl:template match="a"/>
Just to indicate that that particular match statement has a subtile different meaning

Author

Commented:
In the XML, there are several layers of <Item> tags (nested).
So when you say:

<xsl:template match="Item[parent::MenuDataResult">
Will  catch the Item elements that have a parent MenuDataResult

do you mean it will only catch the first level Item tag?



<MenuDataResult>
   <Item>   <-- will it only catch this one
   <Item>   <-- and this one?
      <Menu>
          <Item>
          <Item>

Open in new window

Gertone (Geert Bormans)Information Architect
Top Expert 2006

Commented:
yes

Author

Commented:
In this:

<xsl:template match="Item[child::Menu | ItemType='Submenu']">
Will  catch the Item elements that have a child Menu element or an ItemType  element that has the string value 'Submenu'

do you mean:
" any item that has a child Menu element"
and
"any item that has an ItemType = Submenu"


And by "any item that has a child Menu element" - is it only the first level down? (i.e, not a "grandchild" ?

Thanks.

Gertone (Geert Bormans)Information Architect
Top Expert 2006

Commented:
That is exactly the purpose of that specific match statement:
to be only active on the first level Item
Gertone (Geert Bormans)Information Architect
Top Expert 2006

Commented:
on the other question:
twice yes

- it is a union serving both " any item that has a child Menu element" and "any item that has an ItemType child = 'Submenu'"
- child::Menu is only direct child, not grandchildren,

for grandchildren you would have
<xsl:template match="Item[*/Menu]"> (short syntax)
or
<xsl:template match="Item[child::*/child::Menu]"> (full syntax)

for descendants there is
<xsl:template match="Item[.//Menu]"> (short syntax)
or
<xsl:template match="Item[descendant::Menu]"> (full syntax)



Author

Commented:
Thanks. One (final?) question:

If these are all of my templates:
<xsl:template match="Item[parent::MenuDataResult]">
<xsl:template match="Item[child::Menu | ItemType='Submenu']">
<xsl:template name="makelist" match="Menu">
<xsl:template match="Item[ItemType!='Submenu']">
<xsl:template name="makeButton">

Which one(s) are used by this:
     <xsl:apply-templates select="Item"/>
which is inside the "makelist" template
Gertone (Geert Bormans)Information Architect
Top Expert 2006

Commented:
templates should either have a name attribute or a match attribute, but should not have both at the same time
assuming that template is given a name for identification purposes and that it is used as a match template...

you are looking for Item, so only those with Item in the match statement are candidates
since you apply-templates, and not xsl:call-template, the named templates are not a candidate

this will not be used, since the current context is Menu (see the match attribute of the starting template)
<xsl:template match="Item[parent::MenuDataResult]">

both this one could be active, depending on the values of the childs
<xsl:template match="Item[child::Menu | ItemType='Submenu']">
<xsl:template match="Item[ItemType!='Submenu']">