I'm pulling my hair of at the moment because I'm not quite friends with Muenchian grouping it seems.
I have the following structure in umbraco
Modelliste - Piger - Model - Model - Model - Model Modelliste - Drenge
- Model
- Model
- Model
- Model
On each Model one can select birthyear.
On the page one should be able to search models in a current birthyear in a dropdown box.
The boys and girls tree is running the same set of templates but have different xml in the $currentPage parameter of course.
The way the dropdown box is made is by looping through each birthyear and make sure that it's only written out once.
The problem is that IF the birthyear occurs on the girls section first, then it will NOT appear on the boys section...I guess it has something to do with the key definition somehow...but I suppose that it should run on two different XML sets, right? Since $currentPage should return the XML from the context that it's used in...
I makes sense what you're writing, however it's not build in a way so there is a unique property on boys and girls. The Sex is decided by the name of the "modelliste" - and I don't think that it will make sense to add the a unqiue property to define the sex on each model in this case.
Does it have to be a unqiue property that exits on the node? Or could it be defined in the XSLT in a variable somehow?
Ok, so now I have another challenge with grouping by this method...I'm not sure if this is the way to go about it...
But the case is that I have a list of acitivites that should be split up by month and be listed under each monthname.
In Umbraco I have a list of nodes, which have a date set with a datepicker.
The nodes should be listed in the frontend as follows
Januar Udflugt til badeland Tur i biografen
Februar Fodboldlandskamp i Parken Biograftur
Maj Fiske udflugt Etc.
As the above shows the list of acitivities should only be generated by the dates set on the nodes.
What I can't figure out is how to make sure that the name of the Month is only listed ONCE and then the nodes taking place in that month are listed beneath the correct month.
I hope this has been explained properly and I'm hoping to receive some input on how to solve this on using the muenchian grouping method.
A final note - This is a 4.0.4.2 installation, why I'm using the legacy schema of course.
<!-- Select the container for the event nodes --> <xsl:variablename="events"select="$siteRoot/node[@nodeTypeAlias = 'Event Mappe']"/>
<!-- Key to grab nodes by the month they are in (actually combining year+month to prevent mixing January 2010 with January 2011) --> <xsl:keyname="node-by-month"match="node"use="substring(&eventDate;, 1, 7)"/>
<xsl:templatematch="/"> <!-- Find the first item of each chunk grouped by month --> <xsl:for-eachselect="$events/node[count(. | key('node-by-month', substring(&eventDate;, 1, 7))[1]) = 1]"> <xsl:sortselect="&eventDate;"/>
<!-- Write header for this chunk --> <xsl:apply-templatesselect="."mode="header"/>
<!-- Process all items in this month --> <xsl:apply-templatesselect="key('node-by-month', substring(&eventDate;, 1 ,7))"mode="item"> <xsl:sortselect="&eventDate;"/> </xsl:apply-templates> </xsl:for-each> </xsl:template>
I think it will take a while before I can understand this line fully... <xsl:for-each select="$events/node[count(. | key('node-by-month', substring(&eventDate;, 1, 7))[1]) = 1]">
But someday I might be able to both understand AND explain what it does with my own words :-)
Would have given you "Double 5!" (Etta Cameron style) if I could ;-)
<!-- Select the container for the item nodes --> <xsl:variable name="items" select="$provxml//item" />
<!-- Key to grab nodes by the month they are in (actually combining year+month to prevent mixing January 2010 with January 2011) --> <xsl:key name="item-by-month" match="item" use="concat(substring(&itemDate;, 4, 2),substring(&itemDate;,7,5))" />
<xsl:if test="count($provxml//item) = 0"> <div class="note"> <strong> Ingen posteringer på din konto
</strong> </div> </xsl:if>
<table class="Avance">
<!-- Find the first item of each chunk grouped by month --> <xsl:for-each select="$items[count(. | key('item-by-month', concat(substring(&itemDate;, 4, 2),substring(&itemDate;,7,5)))[1]) = 1]">
<!-- Write header for this chunk --> <xsl:apply-templates select="." mode="header" />
<!-- Process all items in this month --> <xsl:apply-templates select="key('item-by-month', concat(substring(&itemDate;, 4, 2),substring(&itemDate;,7,5)))" mode="item"> <xsl:sort select="&itemDate;" order="descending" /> </xsl:apply-templates>
<!-- Process all totals for this specific month--> <xsl:apply-templates select="." mode="bottom" />
I need to somehow get the sum for those that belong to April 2011 and those that belong to April 2010 seperatly, which is why I can't use the calculated totals from the above XML.
Changing the XML is unfortunately not an option.
Any advise on how to do this? Please tell me if something in the description is not clear enough.
Is the XML actual data, or have they been changed (for testing or similar) - it seems the <monthinvoicetotal> element should be the value you're after, or am I missing something???
The problem is that the <monthinvoicetotal> is the sum for April 2009, 2010 and 2011...not just 2011 for instance. That's why I need to get the sum for each month...
It's giving me a terrible headache...but I'll try to see if there is a chance that I can get the totals delivered for each month/year instead of the totals for each month for all years...(If that makes english???) :-)
But if you do got some sort of nice trick up your sleeve I would looove to hear it.
- but because not only are the dates stored in a crazy format, but the numbers are actually also in a psyched up format (i.e., using Danish decimal comma, instead of a period). So you'll have to convert the numbers before adding them up; Unfortunately you can't do that within the expression, because bla bla bla bla bla... (ask me next time we meet, if you really want to know :-)
So, you need to build a temp variable, convert that to a nodeset, and then call the sum() function on that instead. That's simple enough, right :-)
<!-- $data is something like key('item-by-month', ...)/invoicetotal -->
<!-- Do the temp var thing: -->
<xsl:variable name="values">
<xsl:for-each select="$data">
<!-- Convert from e.g., 1056,00 to 1056.00 -->
<value><xsl:value-of select="translate(., ',', '.')" /></value>
</xsl:for-each>
</xsl:variable>
<xsl:variable name="data-as-numbers" select="make:node-set($values)" />
...
<!-- Calculate sum() -->
<xsl:value-of select="sum($data-as-numbers/value)" />
Grouping Using the Muenchian - Problem...
Hi guys
I'm pulling my hair of at the moment because I'm not quite friends with Muenchian grouping it seems.
I have the following structure in umbraco
Modelliste - Piger
- Model
- Model
- Model
- Model
Modelliste - Drenge
- Model
- Model
- Model
- Model
On each Model one can select birthyear.
On the page one should be able to search models in a current birthyear in a dropdown box.
The boys and girls tree is running the same set of templates but have different xml in the $currentPage parameter of course.
The way the dropdown box is made is by looping through each birthyear and make sure that it's only written out once.
The problem is that IF the birthyear occurs on the girls section first, then it will NOT appear on the boys section...I guess it has something to do with the key definition somehow...but I suppose that it should run on two different XML sets, right? Since $currentPage should return the XML from the context that it's used in...
The code I'm using
<xsl:key name="kbirthyear" match="Model" use="birthyear"/>
<xsl:for-each select="$currentPage/Model[birthyear !=''][generate-id() = generate-id(key('kbirthyear', birthyear)[1])]">
<xsl:sort select="birthyear" order="ascending" />
<option value="{birthyear}">
<xsl:if test="$birthyear = birthyear">
<xsl:attribute name="selected">selected</xsl:attribute>
</xsl:if>
<xsl:value-of select="birthyear" />
</option>
</xsl:for-each>
For now I have just created all possible birthdates manually but I would like to know how to fix the above code if anyone has got any idea about it.
Thanks.
/Jan
Hi Jan,
You want the year select on the Boys' page to only contain years for boys, right? And vice versa for the Girls?
'Cause then you should be able to express that in the key definition by concatenating a property on Model that's unique for each sex, e.g.:
(and then do the same concatenation in the call to key() of course)
/Chriztian
Hi Chriztian
Yes that's exactly what I want.
I makes sense what you're writing, however it's not build in a way so there is a unique property on boys and girls. The Sex is decided by the name of the "modelliste" - and I don't think that it will make sense to add the a unqiue property to define the sex on each model in this case.
Does it have to be a unqiue property that exits on the node? Or could it be defined in the XSLT in a variable somehow?
/Jan
You can pretty much just take the @nodeName (or any other property/attribute on the parent Modelliste, as long as it's different for the two lists):
/Chriztian
That's really cool - now I feel more confident, thanks! :-)
/Jan
Ok, so now I have another challenge with grouping by this method...I'm not sure if this is the way to go about it...
But the case is that I have a list of acitivites that should be split up by month and be listed under each monthname.
In Umbraco I have a list of nodes, which have a date set with a datepicker.
The nodes should be listed in the frontend as follows
Januar
Udflugt til badeland
Tur i biografen
Februar
Fodboldlandskamp i Parken
Biograftur
Maj
Fiske udflugt
Etc.
As the above shows the list of acitivities should only be generated by the dates set on the nodes.
What I can't figure out is how to make sure that the name of the Month is only listed ONCE and then the nodes taking place in that month are listed beneath the correct month.
I hope this has been explained properly and I'm hoping to receive some input on how to solve this on using the muenchian grouping method.
A final note - This is a 4.0.4.2 installation, why I'm using the legacy schema of course.
Cheers.
/Jan
Hi Jan,
Complete sample to start you off - getting your head into the "Muenchian gear" :-)
/Chriztian
Hi Chriztian
Exactly what I was looking for.
I think it will take a while before I can understand this line fully...
<xsl:for-each select="$events/node[count(. | key('node-by-month', substring(&eventDate;, 1, 7))[1]) = 1]">
But someday I might be able to both understand AND explain what it does with my own words :-)
Would have given you "Double 5!" (Etta Cameron style) if I could ;-)
Cheers
/Jan
Hi...me again! :-)
I have the follwoing XSLT
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE xsl:stylesheet [
<!ENTITY nbsp " ">
<!ENTITY tab "	">
<!ENTITY itemDate "invoicedate">
]>
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:make="urn:schemas-microsoft-com:xslt"
xmlns:msxml="urn:schemas-microsoft-com:xslt"
xmlns:library="urn:Chainbox.Web.XslLibrary"
xmlns:shop="urn:Chainbox.Web.XslExtension"
xmlns:umbracoutil="urn:Chainbox.Web.UmbracoUtil"
xmlns:umbraco.library="urn:umbraco.library"
exclude-result-prefixes="msxml make umbraco.library umbracoutil library shop">
<xsl:output method="xml" omit-xml-declaration="yes"/>
<xsl:param name="currentPage"/>
<xsl:variable name="provxml" select="someXmlSource"/>
<!-- Lookup table for monthnames -->
<xsl:variable name="month-mapper">
<month id="01">Januar</month>
<month id="02">Februar</month>
<month id="03">Marts</month>
<month id="04">April</month>
<month id="05">Maj</month>
<month id="06">Juni</month>
<month id="07">Juli</month>
<month id="08">August</month>
<month id="09">September</month>
<month id="10">Oktober</month>
<month id="11">November</month>
<month id="12">December</month>
</xsl:variable>
<xsl:variable name="months" select="make:node-set($month-mapper)" />
<!-- Select the container for the item nodes -->
<xsl:variable name="items" select="$provxml//item" />
<!-- Key to grab nodes by the month they are in (actually combining year+month to prevent mixing January 2010 with January 2011) -->
<xsl:key name="item-by-month" match="item" use="concat(substring(&itemDate;, 4, 2),substring(&itemDate;,7,5))" />
<xsl:template match="/">
<xsl:if test="umbraco.library:Request('debug')">
<textarea>
<xsl:copy-of select="$provxml" />
<xsl:comment />
</textarea>
</xsl:if>
<xsl:if test="count($provxml//item) = 0">
<div class="note">
<strong>
Ingen posteringer på din konto
</strong>
</div>
</xsl:if>
<table class="Avance">
<!-- Find the first item of each chunk grouped by month -->
<xsl:for-each select="$items[count(. | key('item-by-month', concat(substring(&itemDate;, 4, 2),substring(&itemDate;,7,5)))[1]) = 1]">
<xsl:sort select="concat(substring(&itemDate;,7,5),substring(&itemDate;,4,2))" order="descending" data-type="number" />
<!-- Write header for this chunk -->
<xsl:apply-templates select="." mode="header" />
<!-- Process all items in this month -->
<xsl:apply-templates select="key('item-by-month', concat(substring(&itemDate;, 4, 2),substring(&itemDate;,7,5)))" mode="item">
<xsl:sort select="&itemDate;" order="descending" />
</xsl:apply-templates>
<!-- Process all totals for this specific month-->
<xsl:apply-templates select="." mode="bottom" />
</xsl:for-each>
</table>
</xsl:template>
<!-- Header template -->
<xsl:template match="item" mode="header">
<tr>
<td colspan="5">
<h2>
<xsl:value-of select="$months/month[@id = substring(current()/&itemDate;, 4, 2)]" />
<xsl:text> </xsl:text>
<xsl:value-of select="substring(current()/&itemDate;,7,5)" />
</h2>
</td>
</tr>
<tr>
<th class="c1">Ordrenummer</th>
<th class="c2">Navn og adresse</th>
<th class="c3">Dato</th>
<th class="c4">Beløb</th>
<th class="c5">Min avance</th>
</tr>
</xsl:template>
<!-- Template for items -->
<xsl:template match="item" mode="item">
<tr>
<td>
<xsl:value-of select="invoiceid"/>
</td>
<td>
<xsl:value-of select="concat(customername,', ',zipcity)"/>
</td>
<td>
<xsl:value-of select="&itemDate;" />, <xsl:text />
</td>
<td class="Right">
<xsl:value-of select="invoicetotal"/>
<!-- beløb-->
</td>
<td class="Right">
<xsl:value-of select="provision"/>
<!--avance-->
</td>
</tr>
</xsl:template>
<xsl:template match="item" mode="bottom">
<tr>
<td>
</td>
</tr>
<tr class="result">
<th colspan="3" style="text-align:right;">
<xsl:value-of select="$months/month[@id = substring(current()/&itemDate;, 4, 2)]" />
<xsl:text> </xsl:text>
<xsl:value-of select="substring(current()/&itemDate;,7,5)" />'s totaler:
</th>
<th class="Right">
<xsl:value-of select="invoicetotal"/> <!-- needs to be calculated -->
</th>
<th class="Right">
<xsl:value-of select="provision"/> <!-- needs to be calculated -->
</th>
</tr>
</xsl:template>
</xsl:stylesheet>
It generats some output that looks like this:
April 2011
There is generated a long list like the above, where the current month is shown first and the latter months are shown below.
My problem is that I can't figure out how to make sure the totalt for "Beløb" and "Min avance" gets calculated in correct.
I need to calculate the sum of the invoice and provision elements, which are shown on each line.
But since this list gets generated from an XML file that looks like this
<root>
<item>
<invoiceid>45165</invoiceid>
<invoicedate>06/04/2011</invoicedate>
<invoicetotal>216,00</invoicetotal>
<provision>84,50</provision>
<customername>Name</customername>
<zipcity>Address</zipcity>
<monthname>April</monthname>
<monthname1>April</monthname1>
<monthinvoicetotal>2308,00</monthinvoicetotal>
<monthprovisiontotal>944,25</monthprovisiontotal>
</item>
<item>
<invoiceid>45172</invoiceid>
<invoicedate>06/04/2011</invoicedate>
<invoicetotal>192,00</invoicetotal>
<provision>75,00</provision>
<customername>Name</customername>
<zipcity>Address</zipcity>
<monthname>April</monthname>
<monthname1>April</monthname1>
<monthinvoicetotal>2308,00</monthinvoicetotal>
<monthprovisiontotal>944,25</monthprovisiontotal>
</item>
<item>
<invoiceid>47539</invoiceid>
<invoicedate>28/04/2011</invoicedate>
<invoicetotal>336,00</invoicetotal>
<provision>128,00</provision>
<customername>Name</customername>
<zipcity>Address</zipcity>
<monthname>April</monthname>
<monthname1>April</monthname1>
<monthinvoicetotal>2308,00</monthinvoicetotal>
<monthprovisiontotal>944,25</monthprovisiontotal>
</item>
<item>
<invoiceid>44737</invoiceid>
<invoicedate>04/04/2011</invoicedate>
<invoicetotal>-376,00</invoicetotal>
<provision>-150,50</provision>
<customername>Name</customername>
<zipcity>Address</zipcity>
<monthname>April</monthname>
<monthname1>April</monthname1>
<monthinvoicetotal>2308,00</monthinvoicetotal>
<monthprovisiontotal>944,25</monthprovisiontotal>
</item>
<item>
<invoiceid>6932</invoiceid>
<invoicedate>08/04/2010</invoicedate>
<invoicetotal>1052,00</invoicetotal>
<provision>434,75</provision>
<customername>Name</customername>
<zipcity>Address</zipcity>
<monthname>April</monthname>
<monthname1>April</monthname1>
<monthinvoicetotal>2308,00</monthinvoicetotal>
<monthprovisiontotal>944,25</monthprovisiontotal>
</item>
<item>
<invoiceid>9190</invoiceid>
<invoicedate>27/04/2010</invoicedate>
<invoicetotal>584,00</invoicetotal>
<provision>251,50</provision>
<customername>Name</customername>
<zipcity>Address</zipcity>
<monthname>April</monthname>
<monthname1>April</monthname1>
<monthinvoicetotal>2308,00</monthinvoicetotal>
<monthprovisiontotal>944,25</monthprovisiontotal>
</item>
</root>
I need to somehow get the sum for those that belong to April 2011 and those that belong to April 2010 seperatly, which is why I can't use the calculated totals from the above XML.
Changing the XML is unfortunately not an option.
Any advise on how to do this? Please tell me if something in the description is not clear enough.
Cheers
/Jan
Hi Jan,
Is the XML actual data, or have they been changed (for testing or similar) - it seems the <monthinvoicetotal> element should be the value you're after, or am I missing something???
/Chriztian
Hi Christian
Thanks for your reply.
If only my life was THAT easy! :-)
It's actual data.
The problem is that the <monthinvoicetotal> is the sum for April 2009, 2010 and 2011...not just 2011 for instance. That's why I need to get the sum for each month...
It's giving me a terrible headache...but I'll try to see if there is a chance that I can get the totals delivered for each month/year instead of the totals for each month for all years...(If that makes english???) :-)
But if you do got some sort of nice trick up your sleeve I would looove to hear it.
Cheers.
/Jan
Ok - fair enough - can't think of a scenario where that makes sense :-)
It gets worse: Ideally, you should be able to do this:
- but because not only are the dates stored in a crazy format, but the numbers are actually also in a psyched up format (i.e., using Danish decimal comma, instead of a period). So you'll have to convert the numbers before adding them up; Unfortunately you can't do that within the expression, because bla bla bla bla bla... (ask me next time we meet, if you really want to know :-)
So, you need to build a temp variable, convert that to a nodeset, and then call the sum() function on that instead. That's simple enough, right :-)
<!-- $data is something like key('item-by-month', ...)/invoicetotal --> <!-- Do the temp var thing: --> <xsl:variable name="values"> <xsl:for-each select="$data"> <!-- Convert from e.g., 1056,00 to 1056.00 --> <value><xsl:value-of select="translate(., ',', '.')" /></value> </xsl:for-each> </xsl:variable> <xsl:variable name="data-as-numbers" select="make:node-set($values)" /> ... <!-- Calculate sum() --> <xsl:value-of select="sum($data-as-numbers/value)" />
/Chriztian
Haha, nope I'm also a bit surprised to see this output...does not make any sense what so ever...
Thanks for your pointers I will try to see if I can get it to work :-)
/Jan
Hi Chriztian
I managed to get the above working and it's really nice even though it's not ideal. Thank you very much!
Think I owe you a Leffe at CG ;-)
/Jan
Rest assured Jan, I'll take you up on that – Leffe has been known to dissapear anywhere near me :-)
/Chriztian
is working on a reply...