Nesting XSLT template and/or For-each to accomplish 3 levels

  • Thread starter Thread starter Guest
  • Start date Start date
G

Guest

Hi All,

I used an article on XSLT and XML and creating a TOC written on the MSDN
CodeCorner.
ms-help://MS.VSCC.2003/MS.MSDNQTR.2003FEB.1033/dncodecorn/html/corner042699.htm

However, it did'nt quite answer all my questions.
How would one create a 3 level TOC when each item level / node was
differently named (They used Template match and for-each, but the template
match worked as on a 3 level structure they usedf the same named xml tags to
work with the the recursive properties of template matching,

TIA
 
As the URL you posted doesn't work in my machine, could you put in some code
to illustrate your problem?

--
HTH,

Kevin Spencer
Microsoft MVP
Professional Numbskull

Show me your certification without works,
and I'll show my certification
*by* my works.
 
Hi

Have not got the code on me at the mo, on laptop back at home.
However, in the interim, I did find it on the MSDN Help
(ex VStudio.Net) Contents help
in
/WebDevelopment/HTML and Dynamic HTML/Columns/CodeCorner
called DXML: Taking a TOC from XML to DHTML
(where / depicts chapters or nodes in the help (contents) tree

Will however have code on the morrow (we're some 5 hours earlier than
Eastern Seaboard Time), ie end of day here.

thanks
Neal
--
Neal Rogers
University of Cape Town


Kevin Spencer said:
As the URL you posted doesn't work in my machine, could you put in some code
to illustrate your problem?

--
HTH,

Kevin Spencer
Microsoft MVP
Professional Numbskull

Show me your certification without works,
and I'll show my certification
*by* my works.
 
Morning

Heres the code snippet Current XML, XML iro my question and the XSLT
currently employed.

TIA
--
Neal Rogers
University of Cape Town


Neal said:
Hi

Have not got the code on me at the mo, on laptop back at home.
However, in the interim, I did find it on the MSDN Help
(ex VStudio.Net) Contents help
in
/WebDevelopment/HTML and Dynamic HTML/Columns/CodeCorner
called DXML: Taking a TOC from XML to DHTML
(where / depicts chapters or nodes in the help (contents) tree

Will however have code on the morrow (we're some 5 hours earlier than
Eastern Seaboard Time), ie end of day here.

thanks
Neal
 
Morning

Heres the code,
XMl(current) and proposed/questioned and the XSLT which transforms it
currently.

<xsl:stylesheet xmlns:xsl="http://www.w3.org/TR/WD-xsl">

<xsl:template match="/">
<?xml:stylesheet type="text/xsl" href="listN.xsl"?>


<CategoriesList TYPE="Web Dev References">

<Categories>
<CategoryDescr>Vehicles</CategoryDescr>
<CategoryID>1</CategoryID>

<Categories>
<CategoryDescr>OnRoad</CategoryDescr>
<CategoriesID>1</CategoriesID>
<SubCategories>
<SubCategoryId>1</SubCategoryId>
<SubCatDescr>2ndHand</SubCatDescr>
<URL>MainAds.aspx?Vehicles?OnRoad?2ndHand</URL>
<SubCatId>1</SubCatId>
</SubCategories>
<SubCategories>
<SubCategoryId>2</SubCategoryId>
<SubCatDescr>New</SubCatDescr>
<URL>MainAds.aspx?Vehicles?OnRoad?New</URL>
<SubCatId>1</SubCatId>
</SubCategories>
</Categories>

<Categories>
<CategoryDescr>OffRoad</CategoryDescr>
<CategoriesID>2</CategoriesID>
<SubCategories>
<SubCategoryId>1</SubCategoryId>
<SubCatDescr>2ndHand</SubCatDescr>
<URL>MainAds.aspx?Vehicles?OffRoad?2ndHand</URL>
<SubCatId>1</SubCatId>
</SubCategories>
<SubCategories>
<SubCategoryId>2</SubCategoryId>
<SubCatDescr>New</SubCatDescr>
<URL>MainAds.aspx?Vehicles?OffRoad?New</URL>
<SubCatId>1</SubCatId>
</SubCategories>
</Categories>

</Categories>
</CategoriesList>

However had this been instead, Categories, SubCategories and SUbSubCategories
where either SubCategories or SUBSUBCategories could have a URL to an aspx
page with their respective parameters
ie,

<CategoriesList TYPE="Web Dev References">

<Categories>
<CategoryDescr>Vehicles</CategoryDescr>
<CategoryID>1</CategoryID>

<SUBCategories>
<SUBCategoryDescr>OnRoad</SUBCategoryDescr>
<SUBCategoriesID>1</SUBCategoriesID>
<SUBSubCategories>
<SUBSubCategoryId>1</SUBSubCategoryId>
<SUBSubCatDescr>2ndHand</SUBSubCatDescr>
<URL> MainAds.aspx?Vehicles?OnRoad?2ndHand</URL>
<SUBSubCatId>1</SUBSubCatId>
</SUBSubCategories>
..........
.........
.........
</SUBCategories>

<SUBCategories>
<SUBCategoryDescr>OnRoad</SUBCategoryDescr>
<SUBCategoriesID>1</SUBCategoriesID>

<URL> MainAds.aspx?Books?Fiction</URL>
</SUBCategories>



listN.xsl

<HTML>
<HEAD>
<TITLE>List <xsl:value-of select="CategoriesList/@TYPE" /></TITLE>
<LINK REL="stylesheet" TYPE="text/css" HREF="list.css" />
<SCRIPT TYPE="text/javascript" LANGUAGE="javascript"
SRC="listN.js"></SCRIPT>
</HEAD>
<BODY>
<BUTTON ONCLICK="ShowAll('UL')">Show All</BUTTON>
<BUTTON ONCLICK="HideAll('UL')">Hide All</BUTTON>

<H1>List <xsl:value-of select="CategoriesList/@TYPE" /></H1>
<UL><xsl:apply-templates select="CategoriesList/Categories" /></UL>
<UL><xsl:apply-templates select="CategoriesList/Categories/SubCategories"
/></UL>

<!--- <P><BUTTON ONCLICK="window.alert(document.body.innerHTML);">View
HTML</BUTTON></P> -->
</BODY>
</HTML>
</xsl:template>

<xsl:template match="Categories">
<LI CLASS="clsHasKids"><xsl:value-of select="CategoryDescr" />
<UL>
<xsl:for-each select="SubCategories">
<LI>
<A TARGET="main">
<xsl:attribute name="HREF">
<xsl:value-of select="URL"/>
</xsl:attribute>
<xsl:value-of select="SubCatDescr" />
</A>
</LI>
</xsl:for-each>
<xsl:if test="Categories"><xsl:apply-templates /></xsl:if>

</UL>
</LI>
</xsl:template>

<!---
<xsl:template match="SubSubCategories">
<UL>
<xsl:for-each select="SubSubCatDescr">
<LI><xsl:apply-templates /></LI>
</xsl:for-each>
</UL>
</xsl:template>
-->

</xsl:stylesheet>


TIA

--
Neal Rogers
University of Cape Town


Neal said:
Hi

Have not got the code on me at the mo, on laptop back at home.
However, in the interim, I did find it on the MSDN Help
(ex VStudio.Net) Contents help
in
/WebDevelopment/HTML and Dynamic HTML/Columns/CodeCorner
called DXML: Taking a TOC from XML to DHTML
(where / depicts chapters or nodes in the help (contents) tree

Will however have code on the morrow (we're some 5 hours earlier than
Eastern Seaboard Time), ie end of day here.

thanks
Neal
 
Hi Neal,

I find it easy to think of XSL as an "XML Programming Language" of sorts.
That is, it has sequence, selection, and iteration, just as any prgramming
technology does. A Template is similar to a function, with the exception
that along with simply calling it, you can automate the calling of it, by
using <xsl:apply-templates /> without any arguments, in which the process of
the application of Templates begins at the current node and works downward
recursively from there. A Template name or Select condition is the
"signature" of the Template, and any node which matches the signature of the
Template will execute the Template for that node.

In this case, you have a top-level "Categories" node, which contains several
nodes with data about a given Category, and several "SubCategories" nodes,
in a similar structure to the "Categories" node.

If I understand you correctly, you want to extend this to include several
"SubSubCategories" nodes under each "SubCategories" node, to indicate a
further level of nesting.

So, let's analyze the first Template:

This Template is called at the top level by <xsl:apply-templates
select="CategoriesList/Categories" />

That indicates that all nodes under the "CategoriesList" node, with node
names matching "Categories" should be processed by the matching Template (or
"function," as it were).

<xsl:template match="Categories">
<LI CLASS="clsHasKids"><xsl:value-of select="CategoryDescr" />
<UL>
<xsl:for-each select="SubCategories">
<LI>
<A TARGET="main">
<xsl:attribute name="HREF">
<xsl:value-of select="URL"/>
</xsl:attribute>
<xsl:value-of select="SubCatDescr" />
</A>
</LI>
</xsl:for-each>
<xsl:if test="Categories"><xsl:apply-templates /></xsl:if>

</UL>
</LI>
</xsl:template>

What this Template does with SubCategories nodes is handles with
<xsl:for-each select="SubCategories">

Each node within that node contains instructions for adding HTML List Items
to the page, for the various nodes under each "SubCategories" node.

At the end of the Template is this instruction: <xsl:if
test="Categories"><xsl:apply-templates /></xsl:if>

This allows Categories to be contained within other Categories. In other
words, it allows for an infinite recursion of Categories within Categories
within Categories, if desired. By testing each node under a given
"Categories" node, and calling "apply-templates" with no parameters, it will
apply any template that has a name of "Categories" to any node under a given
"Categories" node, which, of course, is the current Template. It is like a
recursive function.

Now, it is important to remember that this is a demonstration or example,
and not supposed to represent any real-life situation. After all, it hardly
makes sense for there to be a node called "SubCategories" when any Category
can, in essence, be a sub-category of any other Category. But it does
illustrate several XSL concepts, including several applications of
Templates, and recursion.

I'm a bit confused about this line, though:

<UL><xsl:apply-templates
select="CategoriesList/Categories/SubCategories"/>

It really does nothing, as all the SubCategories are processed under each
"Categories" node. By the time it reaches this line, the entire XML document
has been processed. It has the effect of adding

<UL></UL>

to the page.

Now, again, for the purpose of self-education, I suppose, you want to add
another level below the "SubCategories" level, with a different name
"SubSubCategories." This is where we talk about the various ways to skin an
XSL cat.

One can use loops or Templates in various situations. I suppose the real
question is, which is most efficient for the particular task? The example
uses both, Templates at the top level, and a loop at the bottom level, which
eliminates the need for another Template. I will follow the same example,
and change the inner loop in the Template to another Template call. The
other Template is much like the first, with a loop for "SUBSubCategories" as
this is now the bottom-most node in the tree:

<xsl:template match="/">
<HTML>
<HEAD>
<TITLE>
List <xsl:value-of select="CategoriesList/@TYPE" />
</TITLE>
<LINK REL="stylesheet" TYPE="text/css" HREF="list.css" />
</HEAD>
<BODY>

<H1>
List <xsl:value-of select="CategoriesList/@TYPE" />
</H1>
<UL>
<xsl:apply-templates select="CategoriesList/Categories" />
</UL>
<UL>
<xsl:apply-templates select="CategoriesList/Categories/SubCategories"/>
</UL>

<!--- <P><BUTTON ONCLICK="window.alert(document.body.innerHTML);">View
HTML</BUTTON></P> -->
</BODY>
</HTML>
</xsl:template>

<xsl:template match="Categories">
<LI CLASS="clsHasKids">
<xsl:value-of select="CategoryDescr" />
<xsl:apply-templates select="SubCategories"/>
</LI>
<xsl:if test="Categories">
<xsl:apply-templates />
</xsl:if>
</xsl:template>

<xsl:template match="SubCategories">
<UL>
<LI CLASS="clsHasKids">
<xsl:value-of select="SubCatDescr" />
<xsl:if test="SUBSubCategories">
<UL>
<xsl:for-each select="SUBSubCategories">
<LI>
<A TARGET="main">
<xsl:attribute name="HREF">
<xsl:value-of select="URL"/>
</xsl:attribute>
<xsl:value-of select="SUBSubCatDescr" />
</A>
</LI>
</xsl:for-each>
<xsl:if test="SubCategories">
<xsl:apply-templates />
</xsl:if>

</UL>
</xsl:if>
</LI>
</UL>
</xsl:template>

Let me know if you have any other questions.

--
HTH,

Kevin Spencer
Microsoft MVP
Professional Numbskull

Show me your certification without works,
and I'll show my certification
*by* my works.

 
Back
Top