The GalleryList is a page that shows all child gallery folders. When on the first level (GalleryList) I loop through all childs with a for-each. If the childs also are of the type GalleryList, I need to select the first child of that.
Looks like you need yourself a dose of the "apply-templates" approach - see if this is close to what you want:
<xsl:template match="/">
<!-- Process the children of $currentPage -->
<xsl:apply-templates select="$currentPage/*[@isDoc]" />
</xsl:template>
<!-- Template for a GalleryList -->
<xsl:template match="GalleryList">
<!-- Take the crop from the first GalleryPage childnode -->
<xsl:apply-templates select="GalleryPage[1]" />
</xsl:template>
<!-- Template for a GalleryPage - take the cropped image -->
<xsl:template match="GalleryPage">
<img src="{galleryImage/crops/crop[@name = 'GalleryListSmall']/@url}" />
</xsl:template>
I have not had a chance to rewrite the code to use templates just yet, but I'm a little confused if your proposed code will work no matter what the currentPage is?
If currentPage is the GalleryList on level 1, the template applied for GalleryList will work correctly, but if currentPage is GalleryList on level 2 the childs will be of the docType GalleryPage. Then the image should be taken directly from that page.
Do I need an if statement to somehow determine what docType the child nodes are? Or is there a neat XSLT trick you can enlighten me with? :) Also, is it possible to call a template which holds the general markup, and from there apply all other templates to render the correct image?
When you use the apply-templates instruction, you tell the processor to collect all the nodes that match the XPath in the select attribute - in this case, all the child document nodes of whichever $currentPage is. They're collected in document order and the processor then looks at each of them in turn and checks if there's a template that "matches" the node, and subsequently use that template to render it with.
If it has a list of GalleryPage nodes it will generate an image for each of their galleryImage properties (the paths inside a template are relative to that template's matching element).
Now, if it has a list of GalleryList nodes instead, it will use the match="GalleryList" template which in turn says "Hey, use the first of my GalleryPage child nodes instead", delegating the actual markup creation from within the GalleryPage template.
So there you have it - as you can see you don't need an if statement to check the document type - instead you write a template for each of the types you need to support. Easily extensible.
If currentPage is GalleryList (root) the GalleryList (1) page renders just fine, but as the only item inside the wrapper. Next, what should have been GalleryList (2) is instead all child pages of itself. When currentPage is GalleryList (2) every child pages renders. For GalleryPage (1) it is fine, but GalleryPage (2) shows up 2 times, GalleryPage (3) shows up 3 times together with GalleryPage (4) which also shows 3 times.
Here's the code:
<xsl:template match="/"> <!-- Process the children of $currentPage --> <xsl:apply-templates select="$currentPage/*[@isDoc and @level = $currentPage/@level +1]" /> </xsl:template>
<!-- Template for a GalleryList --> <xsl:template match="GalleriList"> <!-- Take the crop from the first GalleryPage childnode --> <xsl:apply-templates select="GalleryPage[1 and position() mod 3 = 1]" /> </xsl:template>
<!-- 3-item wrapper for a GalleryPage --> <xsl:template match="GalleryPage"> <div style="height: 300px;"> <xsl:apply-templates select=".|following-sibling::GalleryPage[position() < 3]" mode="inner" /> </div> </xsl:template>
<!-- Template for a GalleryPage to be rendered --> <xsl:template match="GalleryPage" mode="inner"> Contents here... </xsl:template>
Get child node from within for-each loop
Hi.
I'm working on a gallery which have the following structure:
The GalleryList is a page that shows all child gallery folders. When on the first level (GalleryList) I loop through all childs with a for-each. If the childs also are of the type GalleryList, I need to select the first child of that.
Simplified code:
If no image is found, the first child is a GalleryList - I need to select the first child of that.
Sorry for this stupid question, but I can't seem to get my head around the syntax :/
Thanks in advance!
Stefan
Hi Stefan,
Looks like you need yourself a dose of the "apply-templates" approach - see if this is close to what you want:
/Chriztian
Thank you for your reply!
I have not had a chance to rewrite the code to use templates just yet, but I'm a little confused if your proposed code will work no matter what the currentPage is?
If currentPage is the GalleryList on level 1, the template applied for GalleryList will work correctly, but if currentPage is GalleryList on level 2 the childs will be of the docType GalleryPage. Then the image should be taken directly from that page.
Do I need an if statement to somehow determine what docType the child nodes are? Or is there a neat XSLT trick you can enlighten me with? :)
Also, is it possible to call a template which holds the general markup, and from there apply all other templates to render the correct image?
Hi Stefan,
It goes like this:
When you use the apply-templates instruction, you tell the processor to collect all the nodes that match the XPath in the select attribute - in this case, all the child document nodes of whichever $currentPage is. They're collected in document order and the processor then looks at each of them in turn and checks if there's a template that "matches" the node, and subsequently use that template to render it with.
If it has a list of GalleryPage nodes it will generate an image for each of their galleryImage properties (the paths inside a template are relative to that template's matching element).
Now, if it has a list of GalleryList nodes instead, it will use the match="GalleryList" template which in turn says "Hey, use the first of my GalleryPage child nodes instead", delegating the actual markup creation from within the GalleryPage template.
So there you have it - as you can see you don't need an if statement to check the document type - instead you write a template for each of the types you need to support. Easily extensible.
/Chriztian
Thank you very much for your thorough elaboration on how to use templates!
I need to extend the solution to contain a wrapper for every 3 items rendered. It is somewhat working, but the renderings are very inconsistent.
The current structure of the gallery on the site:
Root
- GalleryList (root)
-- GalleryList (1)
---- GalleryPage (1)
-- GalleryList (2)
---- GalleryPage (1)
---- GalleryPage (2)
---- GalleryPage (3)
---- GalleryPage (4)
If currentPage is GalleryList (root) the GalleryList (1) page renders just fine, but as the only item inside the wrapper. Next, what should have been GalleryList (2) is instead all child pages of itself. When currentPage is GalleryList (2) every child pages renders. For GalleryPage (1) it is fine, but GalleryPage (2) shows up 2 times, GalleryPage (3) shows up 3 times together with GalleryPage (4) which also shows 3 times.
Here's the code:
Any suggestions?
is working on a reply...