How to group the elements in XSL? - xslt-2.0

I have an HTML of the following process.
<p class="Reference_Unnum" id="RefId_2"><span class="first_name" dir="Author" value="Klingmann">Klingmann, </span><span class="last_name" dir="Author" value="Anna.">A</span>, <span class="first_name" dir="Author" value="John">John, </span><span class="last_name" dir="Author" value="Kumar">K</span>, <span class="first_name" dir="Author" value="William">William, </span><span class="last_name" dir="Author" value="Jaya">J</span> & <span class="first_name" dir="Author" value="Hannah">Hannah, </span><span class="last_name" dir="Author" value="Leslie.">L</span> <span class="chapter_title" value="Sample Chapter title">Sample Chapter title. </span>In: <span class="first_name" dir="Editor" value="Mihail">Mihail, </span><span class="last_name" dir="Editor" value="Popescu">P</span>, <span class="first_name" dir="Editor" value="Dong">Dong, </span><span class="last_name" dir="Editor" value="Xu">X</span> & <span class="first_name" dir="Editor" value="Hannah">Hannah, </span><span class="last_name" dir="Editor" value="Leslie.">L</span> (eds.) <span class="book_title" value="Sample Book title">Sample Book title.</span></p>
The author and editor name should be group. How it is possible to group first name and last name.
The output should be follow below.
<reference>
<authors>
<author>
<given-name>Klingmann</given-name>
<surname>A</surname>
</author>
<author>
<given-name>John</given-name>
<surname>K</surname>
</author>
<author>
<given-name>William</given-name>
<surname>J</surname>
</author>
<author>
<given-name>Hannah</given-name>
<surname>L</surname>
</author>
</authors>
<chapter-title>Sample Chapter title</chapter-title>
<editors>
<editor>
<given-name>Mihail</given-name>
<surname>P</surname>
</editor>
<editor>
<given-name>Dong</given-name>
<surname>X</surname>
</editor>
<editor>
<given-name>Hannah</given-name>
<surname>L</surname>
</editor>
</editors>
<book-title>Sample Book title</book-title>
</reference>
Thanks in advance.

Here is a sample stylesheet:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:template match="p[#class = 'Reference_Unnum']">
<reference>
<xsl:for-each-group select="span" group-by="(#dir, #class)[1]">
<xsl:choose>
<xsl:when test="current-group()[2]">
<xsl:element name="{lower-case(#dir)}s">
<xsl:for-each-group select="current-group()" group-starting-with="span[#class = 'first_name']">
<xsl:element name="{lower-case(#dir)}">
<xsl:apply-templates select="current-group()"/>
</xsl:element>
</xsl:for-each-group>
</xsl:element>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="."/>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each-group>
</reference>
</xsl:template>
<xsl:template match="span[#class = 'first_name']">
<given-name>
<xsl:value-of select="#value"/>
</given-name>
</xsl:template>
<xsl:template match="span[#class = 'last_name']">
<surname>
<xsl:value-of select="."/>
</surname>
</xsl:template>
<xsl:template match="span[#class = 'chapter_title']">
<chapter-title>
<xsl:value-of select="#value"/>
</chapter-title>
</xsl:template>
<xsl:template match="span[#class = 'book_title']">
<book-title>
<xsl:value-of select="#value"/>
</book-title>
</xsl:template>
</xsl:stylesheet>

Related

Subtraction by decimal number

I have a to subtract the amount -1 based on the condition.Please any one help.
Input:
<JD>
<GP xmlns="">
I xmlns="">
<PK>40</PK>
<A/>
<AMNT>11659650.15</AMNT>
<B/>
<C/>
</I>
<I xmlns="">
<PK>50</PK>
<A/>
<AMNT>11659650.15</AMNT>
<B/>
<C/>
</I>
</GP>
</JD>
Tried with below XSLT and got 1.165964915E7 for 50.
<xsl:for-each select="JD/mo:GP/I">
<xsl:if test="PK='40'">
<xsl:variable name="a" select="AMNT"/>
<xsl:element name="AMT">
<xsl:value-of select="$a"/>
</xsl:element>
</xsl:if>
<xsl:if test="PK='50'">
<xsl:variable name="a" select="AMNT"/>
<xsl:element name="AMT">
<xsl:value-of select="$a - 1"/>
</xsl:element>
</xsl:if>
Considering your given input as following:
<?xml version="1.0" encoding="UTF-8"?>
<Root>
<JD>
<GP>
<I>
<PK>40</PK>
<A />
<AMNT>11659650.15</AMNT>
<B />
<C />
</I>
<I>
<PK>50</PK>
<A />
<AMNT>11659650.15</AMNT>
<B />
<C />
</I>
</GP>
</JD>
</Root>
In XSLT 2.0, you can try it using xs:decimal as below:
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="xs">
<xsl:output omit-xml-declaration="yes" indent="yes" />
<xsl:strip-space elements="*" />
<xsl:template match="/Root">
<xsl:for-each select="JD/mo:GP/I">
<xsl:if test="PK='40'">
<xsl:variable name="a" select="AMNT" />
<xsl:element name="AMT">
<xsl:value-of select="$a" />
</xsl:element>
</xsl:if>
<xsl:if test="PK='50'">
<xsl:variable name="a" select="AMNT" />
<xsl:element name="AMT">
<xsl:value-of select="xs:decimal($a) - 1" />
</xsl:element>
</xsl:if>
</xsl:for-each>
</xsl:template>
In XSLT 1.0, Use the format-number() function:
<xsl:template match="/Root">
<xsl:for-each select="JD/mo:GP/I">
<xsl:if test="PK='40'">
<xsl:variable name="a" select="AMNT" />
<xsl:element name="AMT">
<xsl:value-of select="$a" />
</xsl:element>
</xsl:if>
<xsl:if test="PK='50'">
<xsl:variable name="a" select="AMNT" />
<xsl:element name="AMT">
<xsl:value-of select="format-number($a - 1, '0.##')" />
</xsl:element>
</xsl:if>
</xsl:for-each>
</xsl:template>

making a non logic flat structure hierarchical

I want to group by headers, but when the structure isn't logical the sectioning stops. For example <h2> followed by <h4>. See example. I would like to see the <h4> sectioned when there is no <h3> but I can't seem to get it work. Could someone help me with that? I work with xslt 2.0.
Input:
<?xml version="1.0" encoding="UTF-8"?>
<document id="21" state="Schrijven" documentTypeName="News">
<document track-changes="false" version="1">
<section>
<h1>Title h1</h1>
<p>Some text</p>
<p/>
<h2>Title h2</h2>
<p>Some text</p>
<p/>
<h3>Title h3</h3>
<p>Some text</p>
<p/>
<h2>Title h2</h2>
<p>Some text</p>
<p/>
<h4>Title h4</h4>
<p>Some text</p>
<p/>
</section>
</document>
</document>
Output
<html>
<head>
<meta charset="UTF-8"/>
</head>
<body data-sws-documentkey="id-00021">
<section class="level-newsitem">
<h1 class="nieuws">Title h1</h1>
<p>Some text</p>
<p/>
<section class="level">
<h2>Title h2</h2>
<p>Some text</p>
<p/>
<section class="level">
<h3>Title h3</h3>
<p>Some text</p>
<p/>
</section>
</section>
<section class="level">
<h2>Title h2</h2>
<p>Some text</p>
<p/>
<h4>Title h4</h4>
<p>Some text</p>
<p/>
</section>
</section>
</body>
</html>
Desired Output
<html>
<head>
<meta charset="UTF-8"/>
</head>
<body data-sws-documentkey="id-00021">
<section class="level-newsitem">
<h1 class="nieuws">Title h1</h1>
<p>Some text</p>
<p/>
<section class="level">
<h2>Title h2</h2>
<p>Some text</p>
<p/>
<section class="level">
<h3>Title h3</h3>
<p>Some text</p>
<p/>
</section>
</section>
<section class="level">
<h2>Title h2</h2>
<p>Some text</p>
<p/>
<section class="level">
<h4>Title h4</h4>
<p>Some text</p>
<p/>
</section>
</section>
</section>
</body>
</html>
Stylesheet
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:cwc="urn:cwc"
xmlns:p1="urn:p1"
exclude-result-prefixes="xs cwc p1"
version="2.0">
<xsl:output method="xml" indent="yes" encoding="UTF-8"/>
<xsl:strip-space elements="document meta section div row"/>
<xsl:variable name="DocumentKey">
<xsl:value-of select="concat('id-000', /document[1]/#id)"/>
</xsl:variable>
<xsl:variable name="DocSoort">
<xsl:value-of select="/document/#documentTypeName"/>
</xsl:variable>
<xsl:template match="document">
<html>
<head>
<meta charset="UTF-8"/>
<xsl:if test="./meta/description">
<meta name="description">
<xsl:attribute name="content">
<xsl:value-of select="./meta/description"/>
</xsl:attribute>
</meta>
</xsl:if>
<title><xsl:value-of select="./naam"/></title>
</head>
<body data-sws-documentkey="{$DocumentKey}">
<xsl:choose>
<xsl:when test="$DocSoort='Note'">
<xsl:apply-templates mode="Note"/>
</xsl:when>
<xsl:when test="$DocSoort='News'">
<xsl:apply-templates mode="News"/></xsl:when>
</xsl:choose>
</body>
</html>
</xsl:template>
<xsl:template match="h1" mode="#all">
<xsl:variable name="DocSoorttitel">
<xsl:choose>
<xsl:when test="$DocSoort='Note'">noteitem</xsl:when>
<xsl:when test="$DocSoort='News'">newsitem</xsl:when>
</xsl:choose>
</xsl:variable>
<xsl:variable name="count">
<xsl:value-of select="count(preceding::h1)"/>
</xsl:variable>
<xsl:choose>
<xsl:when test="$count = 0">
<xsl:copy>
<xsl:attribute name="class">
<xsl:value-of select="$DocSoorttitel"/>
</xsl:attribute>
<xsl:apply-templates select="#*[name()!='class']" mode="#current"/>
<xsl:apply-templates mode="#current"/>
</xsl:copy>
</xsl:when>
<xsl:otherwise>
<xsl:copy>
<xsl:apply-templates select="#*" mode="#current"/>
<xsl:apply-templates mode="#current"/>
</xsl:copy>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="naam|meta|lastmodified" mode="#all"/>
<xsl:template match="*/document" mode="#all">
<xsl:choose>
<xsl:when test="not(./section)">
<section>
<xsl:attribute name="class">
<xsl:value-of select="lower-case(concat('sws-', $DocSoort))"/>
</xsl:attribute>
<xsl:call-template name="groupingheaders"/>
</section>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates mode="#current"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="section" mode="#all">
<section>
<xsl:attribute name="class">
<xsl:value-of select="lower-case(concat('level-', $DocSoort))"/>
</xsl:attribute>
<xsl:call-template name="groupingheaders"/>
</section>
</xsl:template>
<xsl:template name="groupingheaders">
<xsl:choose>
<xsl:when test="$DocSoort='Note'">
<xsl:for-each-group select="*" group-starting-with="div[#class = 'letop'][parent::document or parent::section]|h2[parent::document or parent::section][count(text()[normalize-space()]) > 0]">
<xsl:choose>
<xsl:when test="current-group()[1]/self::div[#class = 'letop'][parent::document or parent::section]|current-group()[1]/self::h2[parent::document or parent::section][count(text()[normalize-space()]) > 0]">
<section class="level">
<xsl:call-template name="group2"/>
</section>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="current-group()" mode="#current"/>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each-group>
</xsl:when>
<xsl:when test="$DocSoort='News'">
<xsl:for-each-group select="*" group-starting-with="h2[parent::document or parent::section][count(text()[normalize-space()]) > 0]">
<xsl:choose>
<xsl:when test="current-group()[1]/self::h2[parent::document or parent::section][count(text()[normalize-space()]) > 0]">
<section class="level">
<xsl:call-template name="group2"/>
</section>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="current-group()" mode="#current"/>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each-group>
</xsl:when>
</xsl:choose>
</xsl:template>
<xsl:template name="group2">
<xsl:for-each-group select="current-group()" group-starting-with="h3[parent::document or parent::section][count(text()[normalize-space()]) > 0]">
<xsl:choose>
<xsl:when test="current-group()[1]/self::h3[parent::document or parent::section][count(text()[normalize-space()]) > 0]">
<section class="level">
<xsl:call-template name="group3"/>
</section>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="current-group()" mode="#current"/>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each-group>
</xsl:template>
<xsl:template name="group3">
<xsl:for-each-group select="current-group()" group-starting-with="h4[parent::document or parent::section][count(text()[normalize-space()]) > 0]">
<xsl:choose>
<xsl:when test="current-group()[1]/self::h4[parent::document or parent::section][count(text()[normalize-space()]) > 0]">
<section class="level">
<xsl:call-template name="group4"/>
</section>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="current-group()" mode="#current"/>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each-group>
</xsl:template>
<xsl:template name="group4">
<xsl:for-each-group select="current-group()" group-starting-with="h5[parent::document or parent::section][count(text()[normalize-space()]) > 0]">
<xsl:choose>
<xsl:when test="current-group()[1]/self::h5[parent::document or parent::section][count(text()[normalize-space()]) > 0]">
<section class="level">
<xsl:call-template name="group5"/>
</section>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="current-group()" mode="#current"/>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each-group>
</xsl:template>
<xsl:template name="group5">
<xsl:for-each-group select="current-group()" group-starting-with="h6[parent::document or parent::section][count(text()[normalize-space()]) > 0]">
<xsl:choose>
<xsl:when test="current-group()[1]/self::h6[parent::document or parent::section][count(text()[normalize-space()]) > 0]">
<section class="level">
<xsl:apply-templates select="current-group()" mode="#current"/>
</section>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="current-group()" mode="#current"/>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each-group>
</xsl:template>
<xsl:template match="node()" mode="#all">
<xsl:copy>
<xsl:apply-templates select="node()" mode="#current"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
A regular grouping can be done with a recursive function:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:mf="http://example.com/mf"
exclude-result-prefixes="xs mf"
version="2.0">
<xsl:output method="html" indent="yes"/>
<xsl:param name="prefix" as="xs:string" select="'h'"/>
<xsl:param name="max-level" as="xs:integer" select="6"/>
<xsl:function name="mf:group" as="node()*">
<xsl:param name="nodes" as="node()*"/>
<xsl:param name="level" as="xs:integer"/>
<xsl:for-each-group select="$nodes" group-starting-with="*[local-name() eq concat($prefix, $level)]">
<xsl:choose>
<xsl:when test="self::*[local-name() eq concat($prefix, $level)]">
<section class="level">
<xsl:apply-templates select="."/>
<xsl:sequence select="mf:group(current-group() except ., $level + 1)"/>
</section>
</xsl:when>
<xsl:when test="$level lt $max-level">
<xsl:sequence select="mf:group(current-group(), $level + 1)"/>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="current-group()"/>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each-group>
</xsl:function>
<xsl:template match="#* | node()">
<xsl:copy>
<xsl:apply-templates select="#* , node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="*[h1 | h2 | h3 | h4 | h5 | h6]">
<xsl:copy>
<xsl:sequence select="mf:group(*, 1)"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
That transforms
<document id="21" state="Schrijven" documentTypeName="News">
<document track-changes="false" version="1">
<section>
<h1>Title h1</h1>
<p>Some text</p>
<p/>
<h2>Title h2</h2>
<p>Some text</p>
<p/>
<h3>Title h3</h3>
<p>Some text</p>
<p/>
<h2>Title h2</h2>
<p>Some text</p>
<p/>
<h4>Title h4</h4>
<p>Some text</p>
<p/>
</section>
</document>
</document>
into
<document id="21" state="Schrijven" documentTypeName="News">
<document track-changes="false" version="1">
<section>
<section class="level">
<h1>Title h1</h1>
<p>Some text</p>
<p></p>
<section class="level">
<h2>Title h2</h2>
<p>Some text</p>
<p></p>
<section class="level">
<h3>Title h3</h3>
<p>Some text</p>
<p></p>
</section>
</section>
<section class="level">
<h2>Title h2</h2>
<p>Some text</p>
<p></p>
<section class="level">
<h4>Title h4</h4>
<p>Some text</p>
<p></p>
</section>
</section>
</section>
</section>
</document>
</document>
You need to add your templates for the other elements and maybe, if the first level needs special treatment, extend the function with some conditional checks or write a template or function for the first level.

How to turn-off showing child items for selected Main Menu items in Umbraco CMS?

In order to explain my issue easier, please first see this photo
On my template I have already configured Top navigation but problem is that I am trying to make new menu Item which will be called 'News' and thing is that I don't want that every out of 99 news items I will publish (in next two months), to be autmatically available as sumbenu child item under 'News'.
As I noticed, most of the configuration is under 'umbTopNavigation.xslt'
]>
xmlns:msxml="urn:schemas-microsoft-com:xslt"
xmlns:umbraco.library="urn:umbraco.library"
exclude-result-prefixes="msxml umbraco.library">
<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="/">
<ul id="topNavigation">
<li class="home">
<xsl:if test="$currentPage/#id = $currentPage/ancestor-or-self::* [#level=$level]/#id">
<xsl:attribute name="class">home current</xsl:attribute>
</xsl:if>
Home
</li>
<xsl:for-each select="$currentPage/ancestor-or-self::* [#level=$level]/* [#isDoc and string(umbracoNaviHide) != '1']"> <li>
<xsl:if test="#id = $currentPage/#id">
<xsl:attribute name="class">current</xsl:attribute>
</xsl:if>
<a class="navigation" href="{umbraco.library:NiceUrl(#id)}">
<span><xsl:value-of select="#nodeName"/></span>
</a> </li>
</xsl:for-each> </ul>
</xsl:template>
but I can't figure out what exactly I need to change?
Any help is appreciated and many thanks in advance!
MC2012
First macro
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE xsl:stylesheet [ <!ENTITY nbsp " "> ]>
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxml="urn:schemas-microsoft-com:xslt"
xmlns:umbraco.library="urn:umbraco.library"
exclude-result-prefixes="msxml umbraco.library">
<xsl:output method="xml" omit-xml-declaration="yes"/>
<xsl:param name="currentPage"/>
<xsl:template match="/">
<xsl:variable name="items" select="$currentPage/ancestor-or-self::* [#isDoc and #level = 2]/* [#isDoc and string(umbracoNaviHide) != '1']"/>
<!-- The fun starts here -->
<xsl:if test="count($items) > 0">
<ul>
<xsl:for-each select="$items">
<li>
<a href="{umbraco.library:NiceUrl(#id)}">
<xsl:value-of select="#nodeName"/>
</a>
</li>
</xsl:for-each>
</ul>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
Second Macro
<?xml version="1.0" encoding="utf-8" ?>
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:umbraco.library="urn:umbraco.library"
exclude-result-prefixes="umbraco.library"
>
<xsl:output method="xml" indent="yes" omit-xml-declaration="yes" />
<xsl:param name="currentPage" />
<!-- Specify level of the top node for a language (usually 1) -->
<xsl:variable name="level" select="1" />
<!-- Grab the top node -->
<xsl:variable name="siteRoot" select="$currentPage/ancestor-or-self::*[#level = $level]" />
<xsl:template match="/">
<ul class="menu">
<!-- Create the Home link -->
<li>
<xsl:if test="$currentPage/#id = $siteRoot/#id">
<xsl:attribute name="class">sel</xsl:attribute>
</xsl:if>
<a href="{umbraco.library:NiceUrl($siteRoot/#id)}">
<xsl:value-of select="$siteRoot/#nodeName" />
</a>
</li>
<!-- Process all children of $siteRoot (if any) -->
<xsl:apply-templates select="$siteRoot/*[#isDoc][not(umbracoNaviHide = 1)]" />
</ul>
</xsl:template>
<!-- Generic template for all nav links -->
<xsl:template match="*[#isDoc]">
<li>
<xsl:if test="#id = $currentPage/#id">
<xsl:attribute name="class">sel</xsl:attribute>
</xsl:if>
<a href="{umbraco.library:NiceUrl(#id)}">
<xsl:value-of select="#nodeName" />
</a>
<!-- Render sub menu if necessary -->
<xsl:call-template name="submenu" />
</li>
</xsl:template>
<!-- Template for Inactive links -->
<xsl:template match="*[#isDoc][umbracoNaviInactive = 1]">
<li>
<xsl:if test="#id = $currentPage/#id">
<xsl:attribute name="class">sel</xsl:attribute>
</xsl:if>
<span>
<xsl:value-of select="#nodeName" />
</span>
<!-- Submenu? -->
<xsl:call-template name="submenu" />
</li>
</xsl:template>
<!-- Template checking for, and processing any submenu -->
<xsl:template name="submenu">
<xsl:variable name="subPages" select="*[#isDoc][not(umbracoNaviHide = 1)]" />
<xsl:if test="$subPages">
<ul>
<xsl:apply-templates select="$subPages" />
</ul>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
Ok - you have two options. A quick hack or a full solution.
The quick hack is to update the second macro where the subnav is called and exclude the subnav being called where it's the news page (and you can include other pages in here too)
In this example I've used node ID 1107 to be the ID of your news page, but you will need to update this with your actual news page ID.
<?xml version="1.0" encoding="utf-8" ?>
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:umbraco.library="urn:umbraco.library"
exclude-result-prefixes="umbraco.library"
>
<xsl:output method="xml" indent="yes" omit-xml-declaration="yes" />
<xsl:param name="currentPage" />
<!-- Specify level of the top node for a language (usually 1) -->
<xsl:variable name="level" select="1" />
<!-- Grab the top node -->
<xsl:variable name="siteRoot" select="$currentPage/ancestor-or-self::*[#level = $level]" />
<xsl:template match="/">
<ul class="menu">
<!-- Create the Home link -->
<li>
<xsl:if test="$currentPage/#id = $siteRoot/#id">
<xsl:attribute name="class">sel</xsl:attribute>
</xsl:if>
<a href="{umbraco.library:NiceUrl($siteRoot/#id)}">
<xsl:value-of select="$siteRoot/#nodeName" />
</a>
</li>
<!-- Process all children of $siteRoot (if any) -->
<xsl:apply-templates select="$siteRoot/*[#isDoc][not(umbracoNaviHide = 1)]" />
</ul>
</xsl:template>
<!-- Generic template for all nav links -->
<xsl:template match="*[#isDoc]">
<li>
<xsl:if test="#id = $currentPage/#id">
<xsl:attribute name="class">sel</xsl:attribute>
</xsl:if>
<a href="{umbraco.library:NiceUrl(#id)}">
<xsl:value-of select="#nodeName" />
</a>
<!-- Render sub menu if necessary excluding the news pages -->
<xsl:if test="not(#id=1107)">
<xsl:call-template name="submenu" />
</xsl:if>
</li>
</xsl:template>
<!-- Template for Inactive links -->
<xsl:template match="*[#isDoc][umbracoNaviInactive = 1]">
<li>
<xsl:if test="#id = $currentPage/#id">
<xsl:attribute name="class">sel</xsl:attribute>
</xsl:if>
<span>
<xsl:value-of select="#nodeName" />
</span>
<!-- Submenu? -->
<xsl:call-template name="submenu" />
</li>
</xsl:template>
<!-- Template checking for, and processing any submenu -->
<xsl:template name="submenu">
<xsl:variable name="subPages" select="*[#isDoc][not(umbracoNaviHide = 1)]" />
<xsl:if test="$subPages">
<ul>
<xsl:apply-templates select="$subPages" />
</ul>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
The proper way to do it would be to add a property to your document type to include a property to say do not list children or similar, and then test for that in the XSLT, but that's a much more involved fix, and for that I suggest you read up a bit more on how XSLTs work. Let me know if you want to go down that route and there are plenty of resources I can direct you to
thanks,

XSLT Wrapping text with multiple tags

I have this span element with a class of autbib-pc-bold-italic
<span class="autbib-pc-bold-italic">autbib</span>
I want to create element tags base on the #class attribute value:
My output should be:
<autbib><pc><bold><italic>autbib</italic></bold></pc></autbib>
Here is my xsl templates:
<xsl:template match="span[contains(#class,'autbib')]">
<xsl:call-template name="pbib.loop">
<xsl:with-param name="count" select="count(tokenize(#class, '-'))"/>
<xsl:with-param name="class" select="tokenize(#class, '-')"/>
</xsl:call-template>
</xsl:template>
<xsl:template name="pbib.loop">
<xsl:param name="index" select="1" />
<xsl:param name="count" select="count(tokenize(#class, '-')) + 1"/>
<xsl:param name="class" select="tokenize(#class, '-')"/>
<xsl:element name="{$class[1]}">
<xsl:if test="not($index = $count)">
<xsl:element name="{$class[$index]}">
<xsl:apply-templates/>
</xsl:element>
</xsl:if>
</xsl:element>
<xsl:if test="not($index = $count)">
<xsl:call-template name="pbib.loop">
<xsl:with-param name="index" select="$index + 1" />
</xsl:call-template>
</xsl:if>
</xsl:template>
And have this output which is wrong:
<autbib>
<pc>autbib</pc>
<bold>autbib</bold>
<italic>autbib</italic>
</autbib>
I need to have this output:
<autbib>
<pc>
<bold>
<italic>autbib</italic>
</bold>
</pc>
</autbib>
My problem is that I'm not sure where I should place xsl:apply-template so that tags wrap with each other.
Here is my suggestion:
<xsl:stylesheet
version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="xs">
<xsl:output indent="yes"/>
<xsl:template match="span[contains(#class,'autbib')]">
<xsl:param name="classes" select="tokenize(#class, '-')"/>
<xsl:choose>
<xsl:when test="not($classes[1])">
<xsl:apply-templates/>
</xsl:when>
<xsl:otherwise>
<xsl:element name="{$classes[1]}">
<xsl:apply-templates select=".">
<xsl:with-param name="classes" select="$classes[position() gt 1]"/>
</xsl:apply-templates>
</xsl:element>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
With Saxon 9.4 that transforms the input
<span class="autbib-pc-bold-italic">autbib</span>
into the result
<autbib>
<pc>
<bold>
<italic>autbib</italic>
</bold>
</pc>
</autbib>

Umbraco outputting filesize

I'm trying to output the correct size for pdf files that has been uploaded.
But the only output is 0 - what am I doing wrong?
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE xsl:stylesheet [ <!ENTITY nbsp " "> ]>
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxml="urn:schemas-microsoft-com:xslt"
xmlns:umbraco.library="urn:umbraco.library" xmlns:Exslt.ExsltCommon="urn:Exslt.ExsltCommon" xmlns:Exslt.ExsltDatesAndTimes="urn:Exslt.ExsltDatesAndTimes" xmlns:Exslt.ExsltMath="urn:Exslt.ExsltMath" xmlns:Exslt.ExsltRegularExpressions="urn:Exslt.ExsltRegularExpressions" xmlns:Exslt.ExsltStrings="urn:Exslt.ExsltStrings" xmlns:Exslt.ExsltSets="urn:Exslt.ExsltSets" xmlns:umbraco.contour="urn:umbraco.contour"
exclude-result-prefixes="msxml umbraco.library Exslt.ExsltCommon Exslt.ExsltDatesAndTimes Exslt.ExsltMath Exslt.ExsltRegularExpressions Exslt.ExsltStrings Exslt.ExsltSets umbraco.contour ">
<xsl:output method="xml" omit-xml-declaration="yes" />
<xsl:param name="currentPage"/>
<xsl:variable name="documentTypeAlias" select="string('PdfItem')"/>
<xsl:variable name="size" select="#currentpage/data [#alias = 'umbracoBytes']" />
<xsl:variable name="sizeAndSuffix">
<xsl:choose>
<xsl:when test="$size >= 1073741824">
<xsl:value-of select="format-number($size div 1073741824,'#,###')"/>
<xsl:text>GB</xsl:text>
</xsl:when>
<xsl:when test="$size >= 1048576">
<xsl:value-of select="format-number($size div 1048576,'#,###')"/>
<xsl:text>MB</xsl:text>
</xsl:when>
<xsl:when test="$size >= 1024">
<xsl:value-of select="format-number($size div 1024,'#,###')"/>
<xsl:text>KB</xsl:text>
</xsl:when>
<xsl:when test="$size > 0 and $size < 1024">
<xsl:value-of select="format-number($size div 0,'#,###')"/>
<xsl:text> Bytes</xsl:text>
</xsl:when>
<xsl:otherwise>
<xsl:text>0 Bytes</xsl:text>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:template match="/">
<xsl:for-each select="$currentPage/node [#nodeTypeAlias = $documentTypeAlias and string(data [#alias='umbracoNaviHide']) != '0']">
<div class="pdf">
<a>
<xsl:attribute name="class">pdfmenu</xsl:attribute>
<xsl:attribute name="href"><xsl:value-of select="umbraco.library:GetMedia(./data[#alias='pdf'], 0)/data [#alias = 'umbracoFile']"/></xsl:attribute>
<strong><xsl:value-of select="#nodeName"/><span>
(<xsl:value-of select="$sizeAndSuffix"/>)</span></strong>
<em><xsl:value-of select="data [#alias = 'PDFBeskrivelse']"/></em>
<img>
<xsl:attribute name="src"><xsl:value-of select="data [#alias = 'PDFBillede']"/></xsl:attribute>
<xsl:attribute name="alt"></xsl:attribute>
<xsl:attribute name="height">200</xsl:attribute>
<xsl:attribute name="width">141</xsl:attribute>
</img>
</a>
</div>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
Alright, I've move the size variable into the for-each loop, as it varies per file and fixed a few typos:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE xsl:stylesheet [
<!ENTITY nbsp " ">
]>
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxml="urn:schemas-microsoft-com:xslt"
xmlns:umbraco.library="urn:umbraco.library" xmlns:Exslt.ExsltCommon="urn:Exslt.ExsltCommon" xmlns:Exslt.ExsltDatesAndTimes="urn:Exslt.ExsltDatesAndTimes" xmlns:Exslt.ExsltMath="urn:Exslt.ExsltMath" xmlns:Exslt.ExsltRegularExpressions="urn:Exslt.ExsltRegularExpressions" xmlns:Exslt.ExsltStrings="urn:Exslt.ExsltStrings" xmlns:Exslt.ExsltSets="urn:Exslt.ExsltSets" xmlns:umbraco.contour="urn:umbraco.contour"
exclude-result-prefixes="msxml umbraco.library Exslt.ExsltCommon Exslt.ExsltDatesAndTimes Exslt.ExsltMath Exslt.ExsltRegularExpressions Exslt.ExsltStrings Exslt.ExsltSets umbraco.contour ">
<xsl:output method="xml" omit-xml-declaration="yes" />
<xsl:param name="currentPage"/>
<xsl:variable name="documentTypeAlias" select="string('PdfItem')"/>
<xsl:template match="/">
<xsl:for-each select="$currentPage/node [#nodeTypeAlias = $documentTypeAlias and string(data [#alias='umbracoNaviHide']) != '0']">
<xsl:if test="string(data [#alias = 'pdf']) != ''">
<xsl:variable name="size" select="umbraco.library:GetMedia(data[#alias='pdf'], 0)/data [#alias = 'umbracoFile']" />
<xsl:variable name="sizeAndSuffix">
<xsl:choose>
<xsl:when test="$size >= 1073741824">
<xsl:value-of select="format-number($size div 1073741824,'#,###')"/>
<xsl:text>GB</xsl:text>
</xsl:when>
<xsl:when test="$size >= 1048576">
<xsl:value-of select="format-number($size div 1048576,'#,###')"/>
<xsl:text>MB</xsl:text>
</xsl:when>
<xsl:when test="$size >= 1024">
<xsl:value-of select="format-number($size div 1024,'#,###')"/>
<xsl:text>KB</xsl:text>
</xsl:when>
<xsl:when test="$size > 0 and $size < 1024">
<xsl:value-of select="format-number($size div 0,'#,###')"/>
<xsl:text> Bytes</xsl:text>
</xsl:when>
<xsl:otherwise>
<xsl:text>0 Bytes</xsl:text>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<div class="pdf">
<a>
<xsl:attribute name="class">pdfmenu</xsl:attribute>
<xsl:attribute name="href">
<xsl:value-of select="umbraco.library:GetMedia(data[#alias='pdf'], 0)/data [#alias = 'umbracoFile']"/>
</xsl:attribute>
<strong>
<xsl:value-of select="#nodeName"/>
<span>
(<xsl:value-of select="$sizeAndSuffix"/>)
</span>
</strong>
<em>
<xsl:value-of select="data [#alias = 'PDFBeskrivelse']"/>
</em>
<img>
<xsl:attribute name="src">
<xsl:value-of select="data [#alias = 'PDFBillede']"/>
</xsl:attribute>
<xsl:attribute name="alt"></xsl:attribute>
<xsl:attribute name="height">200</xsl:attribute>
<xsl:attribute name="width">141</xsl:attribute>
</img>
</a>
</div>
</xsl:if>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
That should do the trick.

Resources