Copied to clipboard

Flag this post as spam?

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


  • wolulcmit 357 posts 693 karma points
    Jan 22, 2013 @ 16:39
    wolulcmit
    0

    distinct values and keys with xslt... or the equivalent with Razor

    Have a list of items which I need to group distinctly

    Am using an Xpath AutoComplete ucomponents datatype.
    Am running the latest stable umbraco build 4.11.3.1

    My xslt goes like this:

    <xsl:key name="placeKey" match="XPathAutoComplete" use="Item/@Value" />

    <xsl:apply-templates select="$currentPage/Day[@isDoc]/dayPlace/XPathAutoComplete[generate-id() = generate-id(key('placeKey', Item/@Value)[1])]" />

    <xsl:template match="XPathAutoComplete" >
    <li>
    <xsl:variable name="Node" select="umbraco.library:GetXmlNodeById(Item/@Value)" />
    <a href="{umbraco.library:NiceUrl(Item/@Value)}">
    <xsl:value-of select="$theActualNode/@nodeName" />
    </a>
    </li>
    </xsl:if>

    </xsl:template>

     

    The XML I'm dealing with looks like:

    <dayPlace>
    <XPathAutoComplete Type="c66ba18e-eaf3-4cff-8a22-41b16d66a972">
    <Item Text="Delhi" Value="3411" />
    </XPathAutoComplete>
    </dayPlace>
    <dayPlace>
    <XPathAutoComplete Type="c66ba18e-eaf3-4cff-8a22-41b16d66a972">
    <Item Text="Delhi" Value="3411" />
    </XPathAutoComplete>
    </dayPlace>
    etc....

     

    So it's working perfectly, but only on particular nodes/pages and I cant figure out what the patterns is.
    On some pages generate-id() and my key will never match so no items get output

    for example:
    ID0EACQ0QF0QEAA <-- generate-id
    ID0EACQ0UF0QEAA <-- key doesnt match
    Delhi

    ID0EACP0QF0QEAA <-- generate-id
    ID0EACQ0UF0QEAA <-- key doesnt match
    Delhi

    Perhaps I am just not understanding how xslt keys work?

    Have tried making my keys more specific, but seems to just give the same results, wondering if my XML is on drugs.

    Tried to go down the Exslt.ExsltSets:distinct($nodeset) route, but no joy there either - cant even find a good example of how thats supposed to work.

    I then scrapped Xslt (oh for shame) to try to acheive the same in Razor and ended up with:

    @{

    string parentCurrent = "";
    <nav>
    <h3 class="visuallyhidden">List of countries in this Itinerary</h3>
    <ul class="small-links nav">
    @foreach (var day in @Model.Days.Where("Visible"))
    {
    //We use ParentCurrent to get a unique list of values.

    foreach (var place in @day.dayPlace)
    {
    if (parentCurrent != place.Value)
    {
    <li><a href="@Model.NodeById(place.Value).Url">@place.Text</a></li>
    }
    parentCurrent = place.Value;

    }

    }
    </ul>

    </nav>
    }

    Which works fine and dandy, except after some testing I found that If someone uses the AutoComplete field, saves it and then takes out the original value and saves it blank my xml becomes:

    <dayPlace>
    <XPathAutoComplete Type="c66ba18e-eaf3-4cff-8a22-41b16d66a972" />
    </dayPlace>

    which causes the above razor to freak its shit:

    'char' does not contain a definition for 'Value'

    because these items usually (if populated) get picked up as:

    uComponents.DataTypes.Shared.Models.AutoCompleteItem

    And I dont know in this context how to check the type, or check for an empty value since razor is a bit like voodoo magic for me.

    Appreciate any wise words or slaps to say I'm just doing it wrong.... pretty bummed out that this turned out to be so difficult.

    - Tim

     

     

     

     

  • Chriztian Steinmeier 2800 posts 8791 karma points MVP 8x admin c-trib
    Jan 22, 2013 @ 17:36
    Chriztian Steinmeier
    1

    Hi Tim,

    This is a total longshot from just skimming the code (I know - slap me when we meet again :-) - but I'd expect a need for current() in the comparison here (shortened a bit):

    <xsl:apply-templates select="[...]/XPathAutoComplete[generate-id() = generate-id(key('placeKey', current()/Item/@Value)[1])]" />

     

    /Chriztian

  • Lee Kelleher 4026 posts 15837 karma points MVP 13x admin c-trib
    Jan 22, 2013 @ 18:16
    Lee Kelleher
    101

    Hi Tim,

    Sorry, I read over your post a couple of times and got cross-eyed! (Guess I'm just tired?)

    The brute-force way I'd do this is to get all the nodeIds together in a CSV (just loop through them), then ("if you are using uComponents"™) use the XsltExtension - "ucomponents.strings:RemoveDuplicateEntries()" to get the distinct values.

    Cheers, Lee.

  • wolulcmit 357 posts 693 karma points
    Jan 23, 2013 @ 07:00
    wolulcmit
    0

    Lee you big brute!!!
    Thanks for even taking the time to look (sincerely), I surely wasnt as concise or eloquent as I should have been.

    Looks like Obi-Wan reigns supreme in this episode... current() wasnt the secret sauce I was after unfortunately.
    here's what I ended up with:

    <xsl:template match="/">

    <!-- Run through our items and brute force them into a comma-separated list -->
    <xsl:variable name="comma-separated" >
    <xsl:for-each select="$currentPage/Day[@isDoc]/dayPlace/XPathAutoComplete/Item">
    <xsl:value-of select="@Value" /><xsl:if test="position()!=last()"><xsl:text>,</xsl:text></xsl:if>
    </xsl:for-each>
    </xsl:variable>

    <!-- uComponents to the rescue! - get rid of any dupes -->
    <xsl:variable name="no-duplicates" select="ucomponents.strings:RemoveDuplicateEntries($comma-separated)"/>
    <nav>
    <h3 class="visuallyhidden">List of countries in this Itinerary</h3>
    <ul class="small-links nav">
    <xsl:apply-templates select="umbraco.library:Split($no-duplicates, ',')/value" />
    </ul>
    </nav>

    </xsl:template>

    <xsl:template match="value">
    <li>
    <!-- Sweet sweet node action -->
    <xsl:variable name="sweetsweetNode" select="umbraco.library:GetXmlNodeById(.)" />
    <a href="{umbraco.library:NiceUrl(.)}"><xsl:value-of select="$sweetsweetNode/@nodeName" /></a>
    </li>
    </xsl:template>
  • wolulcmit 357 posts 693 karma points
    Jan 23, 2013 @ 07:42
    wolulcmit
    0

    Also thanks Chriztian!

    I hope the code above doesn't make you weep :)

  • This forum is in read-only mode while we transition to the new forum.

    You can continue this topic on the new forum by tapping the "Continue discussion" link below.

Please Sign in or register to post replies