Copied to clipboard

Flag this post as spam?

This post will be reported to the moderators as potential spam to be looked at


  • Jan Skovgaard 11280 posts 23678 karma points MVP 11x admin c-trib
    Nov 25, 2010 @ 09:58
    Jan Skovgaard
    0

    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

  • Chriztian Steinmeier 2798 posts 8788 karma points MVP 8x admin c-trib
    Nov 25, 2010 @ 10:14
    Chriztian Steinmeier
    1

    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.:

    <xsl:key name="kbirthyear" match="Model" use="concat(sex, birthyear)" />

    (and then do the same concatenation in the call to key() of course)

    /Chriztian

  • Jan Skovgaard 11280 posts 23678 karma points MVP 11x admin c-trib
    Nov 25, 2010 @ 21:59
    Jan Skovgaard
    0

    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

  • Chriztian Steinmeier 2798 posts 8788 karma points MVP 8x admin c-trib
    Nov 25, 2010 @ 22:44
    Chriztian Steinmeier
    1

    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):

    <xsl:key name="kbirthyear" match="Model" use="concat(../@nodeName, birthyear)" />

    /Chriztian 

  • Jan Skovgaard 11280 posts 23678 karma points MVP 11x admin c-trib
    Nov 25, 2010 @ 22:45
    Jan Skovgaard
    0

    That's really cool - now I feel more confident, thanks! :-)

    /Jan

  • Jan Skovgaard 11280 posts 23678 karma points MVP 11x admin c-trib
    Mar 09, 2011 @ 13:16
    Jan Skovgaard
    0

    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

  • Chriztian Steinmeier 2798 posts 8788 karma points MVP 8x admin c-trib
    Mar 10, 2011 @ 01:04
    Chriztian Steinmeier
    1

    Hi Jan,

    Complete sample to start you off - getting your head into the "Muenchian gear" :-)

    <?xml version="1.0" encoding="utf-8" ?>
    <!DOCTYPE xsl:stylesheet [
            <!ENTITY eventDate "data[@alias = 'eventDate']">

    ]>
    <xsl:stylesheet
           
    version="1.0"
           
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
           
    xmlns:umb="urn:umbraco.library"
           
    xmlns:make="urn:schemas-microsoft-com:xslt"
           
    exclude-result-prefixes="umb make"
    >

           
    <xsl:output method="xml" indent="yes" omit-xml-declaration="yes" />

           
    <xsl:param name="currentPage" />
           
    <xsl:variable name="siteRoot" select="$currentPage/ancestor-or-self::*[@level = 1]" />
           
           
    <!-- 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 event nodes -->
           
    <xsl:variable name="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:key name="node-by-month" match="node" use="substring(&eventDate;, 1, 7)" />

           
    <xsl:template match="/">
                   
    <!-- Find the first item of each chunk grouped by month -->
                   
    <xsl:for-each select="$events/node[count(. | key('node-by-month', substring(&eventDate;, 1, 7))[1]) = 1]">
                           
    <xsl:sort select="&eventDate;" />

                           
    <!-- Write header for this chunk -->
                           
    <xsl:apply-templates select="." mode="header" />
                           
                           
    <!-- Process all items in this month -->
                           
    <xsl:apply-templates select="key('node-by-month', substring(&eventDate;, 1 ,7))" mode="item">
                                   
    <xsl:sort select="&eventDate;" />
                           
    </xsl:apply-templates>
                   
    </xsl:for-each>
           
    </xsl:template>

           
    <!-- Header template -->
           
    <xsl:template match="node" mode="header">
                   
    <h2>
                           
    <xsl:value-of select="$months/month[@id = substring(current()/&eventDate;, 6, 2)]" />
                   
    </h2>
           
    </xsl:template>

           
    <!-- Template for items -->
           
    <xsl:template match="node" mode="item">
                   
    <p><xsl:value-of select="@nodeName" /></p>
                   
    <p><xsl:value-of select="substring(&eventDate;, 1, 7)" />, <xsl:text /></p>
           
    </xsl:template>
           
    </xsl:stylesheet>

    /Chriztian

  • Jan Skovgaard 11280 posts 23678 karma points MVP 11x admin c-trib
    Mar 10, 2011 @ 11:19
    Jan Skovgaard
    0

    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

  • Jan Skovgaard 11280 posts 23678 karma points MVP 11x admin c-trib
    Apr 28, 2011 @ 15:21
    Jan Skovgaard
    0

    Hi...me again! :-)

    I have the follwoing XSLT

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE xsl:stylesheet [
      <!ENTITY nbsp "&#x00A0;">
      <!ENTITY tab "&#9;">
      <!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>
            &nbsp;
          </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

    OrdrenummerNavn og adresseDatoBeløbMin avance
    47539 Store, address
    28/04/2011, 336,00 128,00
    45165 Store, address 06/04/2011, 216,00 84,50
    45172 Store, address 06/04/2011, 192,00 75,00
    44737 Store, address 04/04/2011, -376,00 -150,50
    April 2011's totaler: xxx,xx

    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

  • Chriztian Steinmeier 2798 posts 8788 karma points MVP 8x admin c-trib
    Apr 28, 2011 @ 19:24
    Chriztian Steinmeier
    0

    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

  • Jan Skovgaard 11280 posts 23678 karma points MVP 11x admin c-trib
    Apr 28, 2011 @ 22:12
    Jan Skovgaard
    0

    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

  • Chriztian Steinmeier 2798 posts 8788 karma points MVP 8x admin c-trib
    Apr 28, 2011 @ 23:08
    Chriztian Steinmeier
    1

    Ok - fair enough - can't think of a scenario where that makes sense :-)

    It gets worse: Ideally, you should be able to do this:

    <xsl:value-of select="sum(key('item-by-month', ...)/invoicetotal)" />

    - 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)" />
    
    
    Hope that does something for you :-)

    /Chriztian

  • Jan Skovgaard 11280 posts 23678 karma points MVP 11x admin c-trib
    Apr 28, 2011 @ 23:15
    Jan Skovgaard
    0

    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

  • Jan Skovgaard 11280 posts 23678 karma points MVP 11x admin c-trib
    Apr 29, 2011 @ 11:09
    Jan Skovgaard
    0

    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

  • Chriztian Steinmeier 2798 posts 8788 karma points MVP 8x admin c-trib
    Apr 29, 2011 @ 19:27
    Chriztian Steinmeier
    0

    Rest assured Jan, I'll take you up on that – Leffe has been known to dissapear anywhere near me :-)

    /Chriztian

Please Sign in or register to post replies

Write your reply to:

Draft