<xsl:param name="currentPage"/>
<xsl:param name="group-size" select="'2'" />
<xsl:template match="/">
<xsl:variable name="userBlogSource" select="umbraco.library:GetXmlNodeById(umbraco.library:GetDictionaryItem('WeblogNode'))/node [string(data [#alias='umbracoNaviHide']) != '1' and data[#alias='author'] = $currentPage/#id]" />
<xsl:for-each select="$userBlogSource">
<xsl:sort select="data[#alias='dato']" order="descending" />
</xsl:for-each>
<xsl:if test="count($userBlogSource) > 0">
<h3><xsl:value-of select="umbraco.library:GetDictionaryItem('BlogpostsWrittenBy')"/> <xsl:value-of select="$currentPage/#nodeName" />:</h3>
<xsl:apply-templates select="$userBlogSource[(position() mod $group-size) = 1]" />
<ul>
<xsl:for-each select="$userBlogSource">
<li>
<a rel="bookmark" href="{umbraco.library:NiceUrl(#id)}" title="{#nodeName}">
<xsl:value-of select="#nodeName" />
</a>
</li>
</xsl:for-each>
</ul>
</xsl:if>
</xsl:template>
<xsl:template match="node">
<xsl:variable name="postnum" select="position()" />
<div class="weblog-posts-wrap">
<ul>
<xsl:for-each select=". | following-sibling::node[position() < $group-size]">
<li>
<a rel="bookmark" href="{umbraco.library:NiceUrl(#id)}" title="{#nodeName}">
<xsl:value-of select="#nodeName" />
</a>
</li>
</xsl:for-each>
</ul>
</div>
</xsl:template>
When I check the count of $userBlogSource it contains three elements. When I attempt to print the in a regular XSLT for loop it does print the correct elements. But when the variable is passed to the second template matching node, the content is suddenly different. Instead of the three nodes it should contain, it contains 4 nodes by entirely different authors.
Any idea of what I may be doing wrong?
Related
I have a xslt code to convert an xml file to html list. The input and output samples are as follows:
Input:
<Beverages>
<Water/>
<Coffee/>
<Tea>
<BlackTea/>
<WhiteTea id="cti" value="ctv" >Camomile Tea</WhiteTea>
<GreenTea id="gti" value="gtv">
<Sencha/>
<Gyokuro/>
<Matcha/>
<PiLoChun/>
</GreenTea>
</Tea>
</Beverages>
and the Output:
<ul>
<li>
<span class="caret"><Beverages></span>
<ul class="nested">
<li><span><Water/></span></li>
<li><span><Coffee/></span></li>
<li>
<span class="caret"><Tea></span>
<ul class="nested">
<li><span><BlackTea/></span></li>
<li><span><WhiteTea id="cti" value="ctv"></span>Camomile Tea<span></WhiteTea></span></li>
<li>
<span><GreenTea id="gti" value="gtv"></span>
<ul class="nested">
<li><span><Sencha/></span></li>
<li><span><Gyokuro/></span></li>
<li><span><Matcha/></span></li>
<li><span><PiLoChun/></span></li>
</ul>
<span></GreenTea></span>
</li>
</ul>
</li>
</ul>
<span></Beverages></span>
</li>
</ul>
Here is my xslt but it is not exactly the same as what I want:
<xsl:template match="/">
<ul><xsl:apply-templates/></ul>
</xsl:template>
<xsl:template match="*">
<li> <span class="caret"><xsl:value-of select="concat('<',name())" />
<xsl:for-each select="#*">
<xsl:value-of select="concat(' ',name())"/>=<xsl:value-of select="concat('"',.,'"')" />
</xsl:for-each>></span>
<xsl:if test="text()">
<xsl:apply-templates select="text()" />
</xsl:if>
<xsl:if test="*">
<ul class="nested"><xsl:apply-templates/></ul>
</xsl:if>
<span><xsl:value-of select="concat('<','/' ,name() , '>')" /></span></li>
</xsl:template>
The problem is that this code can not differentiate between parent elements and non parent element. for parent elements we need to add class="caret" attribute, but for non parent elements we shouldn't add this class.
This should work for you.
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<ul>
<xsl:apply-templates/>
</ul>
</xsl:template>
<xsl:template match="*">
<li>
<span>
<xsl:if test="*">
<xsl:attribute name="class">
<xsl:value-of select="'caret'"/>
</xsl:attribute>
</xsl:if>
<xsl:value-of select="concat('<',name())"/>
<xsl:for-each select="#*">
<xsl:value-of select="concat(' ', name(), '=', '"', ., '"')"/>
</xsl:for-each>
<xsl:choose>
<xsl:when test="text() or *">
<xsl:value-of select="'>'"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="'\>'"/>
</xsl:otherwise>
</xsl:choose>
</span>
<xsl:if test="text()">
<xsl:value-of select="text()"/>
</xsl:if>
<xsl:if test="*">
<ul class="nested">
<xsl:apply-templates/>
</ul>
</xsl:if>
<xsl:if test="text() or *">
<span>
<xsl:value-of select="concat('<','/' ,name() , '>')"/>
</span>
</xsl:if>
</li>
</xsl:template>
</xsl:stylesheet>
pls check the below code. I am matching the list element and as per the below code the position() function returns correct number of the element with in ul elements i.e 1,2,3 where as if i do the test with position i get only ss,ss,ss . Can anyone let me know where am missing ?
XSL-FO
<xsl:template match="html:li" priority="2">
<fo:list-item>
...
<xsl:value-of select="position()"/> -- this returns 1,2,3
<xsl:if test="position() = 1">
<xsl:text>ss</xsl:text> -- only executes
</xsl:if>
<xsl:if test="position() = 2">
<xsl:text>ssddddd</xsl:text> -- does not only execute
</xsl:if>
<xsl:if test="position() = 3">
<xsl:text>sskkkkkkkkk</xsl:text> -- does not only execute
</xsl:if>
</fo:list-item>
</xsl:template
XSL
<xsl:template match="list">
<xsl:if test="list.item">
<xsl:variable name="styleAttr">
<xsl:text>margin-top: 1em;</xsl:text>
</xsl:variable>
<div>
<xsl:if test="string-length($styleAttr) > 0">
<xsl:attribute name="style">
<xsl:value-of select="$styleAttr"/>
</xsl:attribute>
</xsl:if>
<ul>
<xsl:apply-templates select="node()[not(self::list)]" />
</ul>
</div>
</xsl:if>
</xsl:template>
<xsl:template match="list.item" priority="1">
<li style="padding: 0;">
<div style="margin-bottom: 0.5em;">
<xsl:apply-templates />
<xsl:if test="following-sibling::node()[1][self::list]">
<xsl:apply-templates select="following-sibling::node()[1]" />
</xsl:if>
</div>
</li>
</xsl:template>
I have an xslt navigation, which I want to break into 2 columns, so that after every 6 "li" it creates a new "div"...
I would like to output to be like this:
<ul>
<div class="col">
<li>link</li>
<li>link</li>
<li>link</li>
<li>link</li>
<li>link</li>
<li>link</li>
</div>
<div class="col">
<li>link</li>
<li>link</li>
<li>link</li>
<li>link</li>
<li>link</li>
<li>link</li>
</div>
</ul>
But not quite sure how to do this
My XSLT:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" >
<xsl:output method="xml" omit-xml-declaration="yes" indent="yes" encoding="utf-8" />
<xsl:param name="html-content-type" />
<xsl:template match="/NavigationTree">
<xsl:if test="count(//Page) > 0">
<ul>
<xsl:apply-templates select="Page">
<xsl:with-param name="depth" select="1"/>
</xsl:apply-templates>
</ul>
</xsl:if>
</xsl:template>
<xsl:template match="//Page">
<xsl:param name="depth"/>
<li>
<xsl:attribute name="class">
<xsl:if test="#InPath='True'">inpath </xsl:if>
<xsl:if test="position() = 1">firstitem </xsl:if>
<xsl:if test="position() = count(//Page)">lastitem </xsl:if>
<xsl:if test="#Active='True'">selected</xsl:if>
</xsl:attribute>
<a>
<xsl:attribute name="class">
<xsl:if test="#InPath='True'">inpath </xsl:if>
<xsl:if test="position() = 1">firstitem </xsl:if>
<xsl:if test="position() = count(//Page)">lastitem </xsl:if>
<xsl:if test="#Active='True'">current</xsl:if>
</xsl:attribute>
<xsl:attribute name="href"><xsl:value-of select="#FriendlyHref" disable-output-escaping="yes"/></xsl:attribute>
<xsl:value-of select="#MenuText" disable-output-escaping="yes"/>
</a>
<div class="icon">
<xsl:text disable-output-escaping="yes"><![CDATA[<!--dsfdsfdsf-->]]></xsl:text>
</div>
<xsl:if test="count(Page)">
<ul class="M{#AbsoluteLevel}">
<xsl:apply-templates select="Page">
<xsl:with-param name="depth" select="$depth+1"/>
</xsl:apply-templates>
</ul>
</xsl:if>
</li>
</xsl:template>
</xsl:stylesheet>
A way to do it would be to have a template that matches every 6 Page element:
<xsl:template match="//Page[position() mod 6 = 1]">
<div>
<xsl:apply-templates select="." mode="SecondLevel"/>
<xsl:apply-templates select="following-sibling::Page[position()<6]" mode="SecondLevel"/>
</div>
</xsl:template>
generating the div and applying a second-level template to the current element and its 5 following sibling. The second level template is the one you already have - with an added mode:
<xsl:template match="Page" mode="SecondLevel">
<li>
<xsl:attribute name="class">
<xsl:if test="#InPath='True'">inpath </xsl:if>
<xsl:if test="position() = 1">firstitem </xsl:if>
<xsl:if test="position() = count(//Page)">lastitem </xsl:if>
<xsl:if test="#Active='True'">selected</xsl:if>
</xsl:attribute>
<a>
<xsl:attribute name="class">
<xsl:if test="#InPath='True'">inpath </xsl:if>
<xsl:if test="position() = 1">firstitem </xsl:if>
<xsl:if test="position() = count(//Page)">lastitem </xsl:if>
<xsl:if test="#Active='True'">current</xsl:if>
</xsl:attribute>
<xsl:attribute name="href">
<xsl:value-of select="#FriendlyHref" disable-output-escaping="yes"/>
</xsl:attribute>
<xsl:value-of select="#MenuText" disable-output-escaping="yes"/>
</a>
<div class="icon">
<xsl:text disable-output-escaping="yes"><![CDATA[<!--dsfdsfdsf-->]]></xsl:text>
</div>
</li>
</xsl:template>
I have a website that has pages and subpages as in the image attached.
Some of the subpages belong to First pagge(About Patient Direct), they have setted 'do not show in menu'.
All right, I want to make an xslt file that will generate an html content like this:
Menu Item 1 (including Home page - About Patient Direct)
-submenu page 1 1
Menu Item 2 (including Home page - About Patient Direct)
-submenu page 2 1
-submenu page 2 2
How can I do that?
This is what I have so far
<?xml version="1.0" encoding="UTF-8"?>
]>
<xsl:output method="xml" omit-xml-declaration="yes" />
<xsl:param name="currentPage"/>
<!-- Input the documenttype you want here -->
<xsl:variable name="level" select="1"/>
<xsl:template match="/">
<xsl:if test="$currentPage/#id = $currentPage/ancestor-or-self::* [#level=$level]/#id">
<div class="column">
<h1>
<a href="#">
Home Page - I don't know what to write here
</a>
</h1>
</div>
</xsl:if>
<xsl:for-each select="$currentPage/ancestor-or-self::* [#level=$level]/* [#isDoc and string(umbracoNaviHide) != '1']">
<div class="column">
<h1>
<xsl:choose>
<xsl:when test="name() = 'Link'">
<a href="{current()/linkUrl}" target="_blank">
<xsl:value-of select="#nodeName" />
</a>
</xsl:when>
<xsl:otherwise>
<a href="{umbraco.library:NiceUrl(#id)}">
<xsl:value-of select="#nodeName" />
</a>
</xsl:otherwise>
</xsl:choose>
</h1>
</div>
</xsl:for-each>
</xsl:template>
I have also opened a discussion on http://our.umbraco.org/forum/developers/xslt/33326-How-to-display-sitemapnavigation-for-a-site-using-xslt
I have finally succeeded to do what I have been looking for. Here is the code for those who might be looking for same functionality
<?xml version="1.0" encoding="UTF-8"?>
]>
<xsl:template name="menu">
<xsl:param name="level"/>
<xsl:variable name="RootNode" select="umbraco.library:GetXmlNodeById(1050)" />
<div class="column">
<h1>
<a href="{umbraco.library:NiceUrl($RootNode/#id)}" style="width:200px;">
<xsl:value-of select="$RootNode/#nodeName"/>
</a>
</h1>
<xsl:call-template name="submenu_Homepage">
</xsl:call-template>
</div>
<xsl:if test="count($currentPage/ancestor-or-self::* [#level=$level]/* [#isDoc and string(umbracoNaviHide) != '1']) > '0'">
<xsl:for-each select="$currentPage/ancestor-or-self::* [#level=$level]/* [#isDoc and string(umbracoNaviHide) != '1']">
<div class="column">
<h1>
<xsl:choose>
<xsl:when test="name() = 'Link'">
<a href="{current()/linkUrl}" target="_blank">
<xsl:value-of select="#nodeName" />
</a>
</xsl:when>
<xsl:otherwise>
<a href="{umbraco.library:NiceUrl(#id)}">
<xsl:value-of select="#nodeName" />
</a>
</xsl:otherwise>
</xsl:choose>
</h1>
<xsl:if test="count(current()/* [#isDoc and string(umbracoNaviHide) != '1']) > '0'">
<xsl:call-template name="submenu">
<xsl:with-param name="level" select="$level+1"/>
</xsl:call-template>
</xsl:if>
</div>
</xsl:for-each>
</xsl:if>
</xsl:template>
<xsl:template name="submenu">
<xsl:param name="level"/>
<ul class="level_{#level}">
<xsl:for-each select="current()/*[#isDoc and string(umbracoNaviHide) != '1']">
<li>
<xsl:if test="position() != last()">
<xsl:attribute name="class">bottom_border</xsl:attribute>
</xsl:if>
<a href="{umbraco.library:NiceUrl(#id)}">
<xsl:value-of select="#nodeName"/>
</a>
<!--case when we have third menu level-->
<xsl:if test="count(current()/* [#isDoc and string(umbracoNaviHide) != '1']) > '0'">
<xsl:call-template name="submenu">
<xsl:with-param name="level" select="$level+1"/>
</xsl:call-template>
</xsl:if>
</li>
</xsl:for-each>
</ul>
</xsl:template>
<xsl:template name="submenu_Homepage">
<ul>
<xsl:for-each select="$currentPage/ancestor-or-self::*/* [#isDoc and string(umbracoNaviHide) = '1']">
<li>
<xsl:if test="position() != last()">
<xsl:attribute name="class">bottom_border</xsl:attribute>
</xsl:if>
<xsl:choose>
<xsl:when test="name() = 'Link'">
<a href="{current()/linkUrl}" target="_blank">
<xsl:value-of select="#nodeName" />
</a>
</xsl:when>
<xsl:otherwise>
<a href="{umbraco.library:NiceUrl(#id)}">
<xsl:value-of select="#nodeName" />
</a>
</xsl:otherwise>
</xsl:choose>
</li>
</xsl:for-each>
</ul>
</xsl:template>
I have a set of items which I am grouping using the muenchian method using keys. This is working great, however when I try to do things with the first x number of items it is doing it on the x number of items in each group rather than across the whole set of results. How would I get the individual position of each item accross the whole collection?
<xsl:key name="pictures-by-productid" match="/dsQueryResponse/Rows/Row" use="#ProductId" />
<xsl:template match="/">
<div style="border:1px solid red; float:left;">
<xsl:apply-templates select="/" mode="sub">
</xsl:apply-templates>
</div>
</xsl:template>
and the second template
<xsl:template match="/" mode="sub"> <xsl:for-each select="/dsQueryResponse/Rows/Row[count(. | key('pictures-by-productid', #ProductId)[1]) = 1]">
<xsl:for-each select="key('pictures-by-productid', #ProductId)">
<xsl:sort select="#PictureType" />
<div style="float:left; margin:2px;">
<img src="{#ThumbNailUrl}" width="58" /> <br />
Download
<xsl:number value="position()" format="1. " />
<xsl:value-of select="." />
</div>
</xsl:for-each>
</xsl:for-each>
</xsl:template>
<xsl:key
name="pictures-by-productid"
match="/dsQueryResponse/Rows/Row"
use="#ProductId"
/>
<xsl:template match="/">
<div style="border:1px solid red; float:left;">
<!-- iterate the group, sorted by PictureType… -->
<xsl:for-each select="/dsQueryResponse/Rows/Row[
count(. | key('pictures-by-productid', #ProductId)[1]) = 1
]">
<xsl:sort select="#PictureType">
<!-- …and output only if among the fist 6 items -->
<xsl:if test="position() <= 6">
<xsl:apply-templates
mode="picture"
select="key('pictures-by-productid', #ProductId)"
/>
</xsl:if>
</xsl:for-each>
</div>
</xsl:template>
<xsl:template match="/dsQueryResponse/Rows/Row" mode="picture">
<div style="float:left; margin:2px;">
<img src="{#ThumbNailUrl}" width="58" /> <br />
<xsl:text>Download </xsl:text>
<xsl:number value="position()" format="1. " />
<xsl:value-of select="." />
</div>
</xsl:template>