Copied to clipboard

Flag this post as spam?

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


  • Tom Cowling 144 posts 342 karma points
    Jun 27, 2014 @ 11:51
    Tom Cowling
    0

    Selecting distinct values

    Hi,

    I have created a datatype from a checklist. This holds a number of different values that are essentially tags for one set of child nodes. This set of child nodes are 'Publication' nodes. Each publication can have multiple authors that are in the checkbox list.

    What I would like as a final outcome is for a page called "Authors" where I can produce a list of links to each of the items for this list. When a user clicks on an author, is then goes to a page that lists all the nodes where they are ticked as a centre author.

    I'm currently working on the first stage of this and have come up with what I think is the right approach (open to suggestion!) for what I want to achieve. I currently have a couple of problems:

    • The list is being produced as a string with commas, I guess I will need to use umbraco.library:Split to split the results up before doing some distinct selecting(?) Solving this by make the second problem void.

    • If I select author 1 and author 2 for he first publication and auhor 1 and author 2 for the second publication, I only get one result as it's reading the string, comparing it and as they're the same it's getting rid of one to make it distinct (which I guess is exactly what I've asked it to do!)
    <xsl:param name="currentPage"/>
    <xsl:key name="PubKey" match="Publication" use="centreAuthors"/>

    <xsl:template match="/">
    <xsl:for-each select="$currentPage/ancestor-or-self::Home//Publication[@isDoc][generate-id() = generate-id(key('PubKey', centreAuthors)[1])]">
    <xsl:sort select="centreAuthors" order="ascending" />
    <p><xsl:value-of select="centreAuthors"/></p>
    </xsl:for-each>
    </xsl:template>

    </xsl:stylesheet>

     

    If anyone can help me out, I'd really appreciate it! Not sure if a better solution would be to read in the checklist iteself and pull out each of the values rather than looking through the nodes to see what values are assigned?

     

    Thanks,

    Tom

  • Tom Cowling 144 posts 342 karma points
    Jul 03, 2014 @ 13:54
    Tom Cowling
    0

    bump :(

  • Chriztian Steinmeier 2798 posts 8787 karma points MVP 7x admin c-trib
    Jul 03, 2014 @ 14:19
    Chriztian Steinmeier
    0

    Hi Tom,

    I'd like to help you out but I don't think I understand completely, so I'll post a question first:

    • Does the authors only "exist" as prevalues on a datatype or are they separate documents (which the checklist pulls in as prevalues)?

    XSLT can do some very powerful lookups between large nodesets, but requires values to be nodes (as opposed to strings), so yes, you'll need to split the CSV data into nodes if you want to solve this in a good way.

    /Chriztian

  • Tom Cowling 144 posts 342 karma points
    Jul 03, 2014 @ 14:27
    Tom Cowling
    0

    Hi Chriztian,

    Thanks a lot for your reply - What I have done is create a new datatype as a checkbox and popped the values in there. These values will change as more authors are added to the list.

    To add the authors as nodes would you suggest I create a new document type as an author and then add each person as a node? If so, how could I then tie an author to a publication? Could I build a checkbox list out of existing nodes?

    Thanks,

    Tom

  • Tom Cowling 144 posts 342 karma points
    Jul 03, 2014 @ 14:36
    Tom Cowling
    0

    I've created some nodes under a new document type and used the ultimate picker tool, so now have a checkbox list filled with authors as nodes rather than a string.

    Any further advice would be much appreciated and I'm now in unfamiliar territory!

     

    Thanks,

    Tom

  • Chriztian Steinmeier 2798 posts 8787 karma points MVP 7x admin c-trib
    Jul 03, 2014 @ 14:38
    Chriztian Steinmeier
    0

    Hi Tom,

    Oh yes - depends a little on the version of Umbraco you're using, though - but if you have an "Authors" section with separate "Author" documents, you can set up an "Author Picker" datatype using the "XPath CheckBoxList" Property Editor, which can save the picked authors as XML, which makes it very easy to do any lookups between publications. Also, you'd have your distinct list of authors just by listing all the "Author" nodes created - maybe filtering on actually being picked on a publication, which would also be pretty straightforward...

    Still, if you for some reason can't use this ultimate setup, it's of course possible to do what you need - just takes a little more work :-)

    Which version of Umbraco are you using?

    /Chriztian

  • Chriztian Steinmeier 2798 posts 8787 karma points MVP 7x admin c-trib
    Jul 03, 2014 @ 14:48
    Chriztian Steinmeier
    0

    Allright - great!

    So refresh my memory, how does the XML look for the Ultimate Picker? Is it a bunch of <value>1234</value><value>2039</value> nodes?

    /Chriztian

  • Tom Cowling 144 posts 342 karma points
    Jul 03, 2014 @ 14:51
    Tom Cowling
    0

    Using version v6.2.1

    I can set it as a XPath CheckBoxList if that will make the process easier. Current setup below. Feel free to comment - I can set it up differently if need be. The site is still in development stage so can be changed as I go along.

    Got a 'publicationHome' document type which can only have 'publication' children.

        'publication' document types have a datatype available to them that is an ultimate picker with the top node set to list all children of 'centreAuthor'. This can be changed to XPath CheckBoxList with some guidance. :)

    Got a 'centreAuthors' document type which can only have 'centreAuthor' children

     

  • Tom Cowling 144 posts 342 karma points
    Jul 03, 2014 @ 14:58
    Tom Cowling
    0

    So refresh my memory, how does the XML look for the Ultimate Picker? Is it a bunch of <value>1234</value><value>2039</value> nodes?

     

    Not sure how I'd get that to show as a list.. I'm good at editing pre-existing code, but rubbish at writing it from scratch! I guess I'd need to select a publication node and then do a for loop to publish all values..? Or is the question much simpler than that?

  • Chriztian Steinmeier 2798 posts 8787 karma points MVP 7x admin c-trib
    Jul 03, 2014 @ 15:10
    Chriztian Steinmeier
    0

    Hi Tom - three ways to get to know the XML (listed in increasing preferred order):

    1. Open the the /App_Data/Umbraco.config file
    2. In a macro, write the following code:

      <textarea><xsl:copy-of select="$currentPage" /></textarea>
      
    3. Install my XMLDump package :-)

    /Chriztian

  • Chriztian Steinmeier 2798 posts 8787 karma points MVP 7x admin c-trib
    Jul 03, 2014 @ 15:16
    Chriztian Steinmeier
    0

    Okay - so here's a crude example of how to do the lookup once you have a connection between the two:

    (Note that you may need to change a couple of XPaths and aliases, but we'll try to solve that along the way)

    <?xml version="1.0" encoding="utf-8" ?>
    <xsl:stylesheet
        version="1.0"
        xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
        xmlns:umb="urn:umbraco.library"
        exclude-result-prefixes="umb"
    >
    
        <xsl:output method="xml" indent="yes" omit-xml-declaration="yes" />
    
        <xsl:param name="currentPage" />
    
        <!-- Grab a reference to the site's root -->
        <xsl:variable name="siteRoot" select="$currentPage/ancestor-or-self::*[@level = 1]" />
    
        <!-- Point to the two "roots" relative to the $siteRoot -->
        <xsl:variable name="authorsRoot" select="$siteRoot/../centreAuthors" />
        <xsl:variable name="pubRoot" select="$siteRoot/publicationHome" />
    
        <xsl:template match="/">
            <h2>Listing authors and their publications</h2>
            <ul>
                <xsl:apply-templates select="$authorsRoot/centreAuthor" />
            </ul>
        </xsl:template>
    
        <!-- Template for an author -->
        <xsl:template match="centreAuthor">
            <xsl:variable name="authorID" select="@id" />
            <li>
                <strong><xsl:value-of select="@nodeName" /></strong>
                <!-- List all publications this author is credited with: -->
                <xsl:apply-templates select="$pubRoot//publication[authors//value = $authorID]" />
            </li>
        </xsl:template>
    
        <!-- Template for a publication -->
        <xsl:template match="publication">
            <a href="{umb:NiceUrl(@id)}"><xsl:value-of select="@nodeName" /></a>
            <xsl:if test="not(position() = last())">, </xsl:if>
        </xsl:template>
    
    </xsl:stylesheet>
    

    /Chriztian

  • Tom Cowling 144 posts 342 karma points
    Jul 03, 2014 @ 17:32
    Tom Cowling
    0

    Thanks a lot for this Chriztian - really appreciate this!

     

    Not sure why, but Umbraco doesn't like line 33:

    Error occuredError in XSLT at line 33, char 13
    31:       <strong><xsl:value-of select="@nodeName" /></strong>
    32:       <!-- List all publications this author is credited with: -->
    33: >>>   <xsl:apply-templates select="$publicationHome//publication[authors//value = $authorID]" /> <<<
    34:       </li>
    35:       </xsl:template>

    Not sure if it's a syntax error or that something doesn't exist somewhere.. I've named my picker authors to fit in with the code and all nodes have correct aliases (well done!)

  • Chriztian Steinmeier 2798 posts 8787 karma points MVP 7x admin c-trib
    Jul 03, 2014 @ 17:40
    Chriztian Steinmeier
    0

    Oh - my bad!

    The $publicationHome variable doesn't exist - I called it $pubRoot, so that's what it should say there. I've fixed the code above, for anyone else...

    /Chriztian

  • Tom Cowling 144 posts 342 karma points
    Jul 03, 2014 @ 17:44
    Tom Cowling
    0

    Cool. It validates fine now and saves okay.

    Output is just the contents of the h2..  I've gone into the test publications I have listed in the system and tagged a few of the centreAuthors fro mthe checklist on each of them, but still not working.

  • Tom Cowling 144 posts 342 karma points
    Jul 03, 2014 @ 17:48
    Tom Cowling
    0

    Could it be something to do with where the nodes sit in the structure?

        <xsl:variablename="authorsRoot"select="$siteRoot/../centreAuthors"/>
       
    <xsl:variablename="pubRoot"select="$siteRoot/publicationHome"/>
  • Chriztian Steinmeier 2798 posts 8787 karma points MVP 7x admin c-trib
    Jul 03, 2014 @ 18:01
    Chriztian Steinmeier
    0

    Hi Tom,

    Yes - the XPaths need to select the right nodes. The ones I've written (provided the aliases are correct) assume the following structure:

    Content
       Home
          Publications (alias: publicationHome)
          ...
       Authors (alias: centreAuthors)
          ...
    

    So your "Home" and "Authors" nodes are both at level 1 (?)

    That's just inferred from your screenshot, but I could be wrong (noooo??? :)

    But maybe your Authors are really inside the site? In that case:

    Content
       Home
          Publications (alias: publicationHome)
          ...
          Authors (alias: centreAuthors)
          ...
    

    Change to this for the authorsRoot variable:

    <xsl:variablename="authorsRoot"select="$siteRoot/centreAuthors"/>
    

    /Chriztian

  • Tom Cowling 144 posts 342 karma points
    Jul 03, 2014 @ 18:05
    Tom Cowling
    0

    No the first one is correct - Didn't want the Authors to inherit anything from the rest of the site..

     

    Full node structure screenshot attached..

     

  • Tom Cowling 144 posts 342 karma points
    Jul 04, 2014 @ 12:33
    Tom Cowling
    0

    Using the textarea method you recomended earlier, I've managed to tweak the paths. When I've done the following it seems to point to the correct places:

       <xsl:variable name="pubRoot" select="$siteRoot/publicationHome" />
    <xsl:variable name="authorsRoot" select="$siteRoot//centreAuthors" />

    Would that make sense?

    The output for this one doesn't produce anything useful though..  I've tried different variations on /, /.. and // but nothing seems to work.. :(

    <xsl:copy-of select="$authorsRoot/centreAuthor" />

     

  • Chriztian Steinmeier 2798 posts 8787 karma points MVP 7x admin c-trib
    Jul 04, 2014 @ 12:50
    Chriztian Steinmeier
    0

    Hi Tom,

    Your screenshot shows your $siteRoot ("WTCGHR") at level 1, which makes the original paths correct ($siteRoot/publicationHome and $siteRoot/../centreAuthors) - but only if you're running the macro from a page within the $siteRoot site - so if you're running the macro in the XSLT Visualizer, make sure to select a $currentPage within that site.

    Does that make sense to you?

    /Chriztian

  • Tom Cowling 144 posts 342 karma points
    Jul 04, 2014 @ 12:56
    Tom Cowling
    0

    The macro is running on the Publications > By Author page so it should work.. Should it not? Debugging is the worst! :(

    I'll put it back to how it was. The macro stops rendering at the following point:

    <xsl:apply-templatesselect="$authorsRoot/centreAuthor"/>

    It pops the h2 and the <ul> tags and then doesn't pop any more information in..

  • Chriztian Steinmeier 2798 posts 8787 karma points MVP 7x admin c-trib
    Jul 04, 2014 @ 13:09
    Chriztian Steinmeier
    0

    Well, well, well :-)

    Two places for where stuff goes bonkers:

    1. The aliases must be exactly as we've stated, case-sensitivity and all...
    2. The authors data-type - I guess there could be a problem here; we never confirmed the output of that one...

    Do you get an empty <ul /> in the source, or do you get an error message? (Use "view source" - not the dev console...)

    /Chriztian

  • Tom Cowling 144 posts 342 karma points
    Jul 04, 2014 @ 13:22
    Tom Cowling
    0

    Okay. I've check re-checked and checked again with the aliases and can't see anything wrong there.

    And yes - it produces a <ul />

    Ultimate picker returns a set of numerical values. If more than one is selected, they are comma seperated..

  • Tom Cowling 144 posts 342 karma points
    Jul 04, 2014 @ 13:32
    Tom Cowling
    0

    Just looked in the app_data umbraco.config - the Ultimate picker seems to be adding stuff to the nodes in the following format:

    <centreAuthors><![CDATA[1178,1182]]></centreAuthors>

    <centreAuthors><![CDATA[1178]]></centreAuthors>


    Not sure how helpful that is?

  • Chriztian Steinmeier 2798 posts 8787 karma points MVP 7x admin c-trib
    Jul 04, 2014 @ 13:44
    Chriztian Steinmeier
    0

    That's it, right there :-)

    Alright - I'll come back with a fix...

    /Chriztian

  • Chriztian Steinmeier 2798 posts 8787 karma points MVP 7x admin c-trib
    Jul 04, 2014 @ 23:32
    Chriztian Steinmeier
    0

    Hi Tom,

    Just to be clear: If you're getting an empty <ul/> it can only mean one of two things: Your "Centre Authors" document type alias is not centreAuthors OR your "Centre Author" document type alias is not centreAuthor.

    What do you get if you dump the $authorsRoot variable? (<xsl:copy-of select="$authorsRoot" />)

    /Chriztian

  • Tom Cowling 144 posts 342 karma points
    Jul 05, 2014 @ 00:32
    Tom Cowling
    0

    Just double checked the two of them - both correct.

    When I do a dump of that it doesn't display anything (just a blank space and then the footer html of the site)

    If I do a dump using double slash:

    <xsl:variablename="authorsRoot"select="$siteRoot//centreAuthors"/>

    i get the following:

      <centreAuthors>1179</centreAuthors>
      <centreAuthors>1178,1182</centreAuthors>
      <centreAuthors>1178</centreAuthors>

  • Tom Cowling 144 posts 342 karma points
    Jul 05, 2014 @ 00:35
    Tom Cowling
    0

     

    Document types (just to make sure I'm not going insane!):

     

  • Chriztian Steinmeier 2798 posts 8787 karma points MVP 7x admin c-trib
    Jul 05, 2014 @ 00:45
    Chriztian Steinmeier
    0

    Hi Tom,

    Right, when you do the double-slash, you're getting the centreAuthors properties of the publication nodes below $siteRoot.

    So this means that $authorsRoot does not select the root node of the authors - The alias is correct, as seen on your screenshot, so must be the path...

    This one is way inefficient but it's guaranteed to get the right one, which is what we're after right now:

    <xsl:variable name="authorsRoot" select="$currentPage/ancestor-or-self::root//centreAuthors[@isDoc]" />
    

    Translated from XPath into english: "Go from the current page up to the ancestor named 'root', then search every nook and cranny for a document named 'centreAuthors'. Grab a hold of that, and don't let go!"

    /Chriztian

  • Tom Cowling 144 posts 342 karma points
    Jul 05, 2014 @ 10:08
    Tom Cowling
    0

    I tried it and it didn't work so I had another look at the node itself..

    I'm so, so sorry! Somehow it wasn't published anymore..

    I've reverted back to your original code and that also works now (as you said it would)

    <xsl:variable name="authorsRoot" select="$siteRoot/../centreAuthors" />

    That now produces the following:

      <centreAuthors id="1177" parentID="-1" level="1" creatorID="0" sortOrder="1" createDate="2014-07-03T13:43:34" updateDate="2014-07-05T09:09:38" nodeName="Centre Authors" urlName="centre-authors" path="-1,1177" isDoc="" nodeType="1175" creatorName="Tom Cowling" writerName="Tom Cowling" writerID="0" template="0" nodeTypeAlias="centreAuthors" />

    All the centreAuthor nodes under that are published, but still not showing (just getting a <ul />)

     

    So frustratingly close!!

  • Chriztian Steinmeier 2798 posts 8787 karma points MVP 7x admin c-trib
    Jul 06, 2014 @ 19:22
    Chriztian Steinmeier
    100

    Hi Tom,

    If you get that exact result above, the author nodes below it are not published - they should appear in the XML too, if they're published; but I'm not sure if you've removed them for brevity...?

    In fact, as long as you get an empty <ul/> the code never enters the template for a single author, which in turn means that there are no authors (published)...

    /Chriztian

    PS: THis is how you should use the Split() extension to get the referenced publications, when we get the rest working:

    <div>
        <xsl:apply-templates select="$pubRoot/publication[umb:Split(centreAuthors, ',')/value = $authorID]" />
    </div>
    
  • Tom Cowling 144 posts 342 karma points
    Jul 07, 2014 @ 10:53
    Tom Cowling
    0

    Bizarre. They were all published, but not working.I unpublished them all and then republished - works a treat now!

    I've also added in the extra code you included at the bottom there and it all works beautifully.

     

    Thank you so much for your help and support - it's very much appreciated.

     

    Tom

  • Chriztian Steinmeier 2798 posts 8787 karma points MVP 7x admin c-trib
    Jul 07, 2014 @ 11:18
    Chriztian Steinmeier
    0

    Awesome!

    You're welcome :)

    /Chriztian

  • Tom Cowling 144 posts 342 karma points
    Jul 07, 2014 @ 15:19
    Tom Cowling
    0

    One more thing then I promise I'll leave you alone! :)

     

    I've modifed that code slightly so that it now runs through and shows a list of Authors on the author page and creates a link with the author's ID. This ID is passed a querystring to the results page.

    I've then used the code provided to run through the list and find any publications by the author using the string passed to that page.

    It produces a list of publications as expected and this list is correct, but it's adding them to the list the same number times as there are authors in the checklist. I understand why it's doing it as it's running through all the authors and then building up a template. What I don't get is how to tweak it so it produces a list of publications produced by the author of the querystring. Code below:

    <?xml version="1.0" encoding="utf-8" ?>
    <xsl:stylesheet
        version="1.0"
        xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
        xmlns:umb="urn:umbraco.library"
        exclude-result-prefixes="umb"
    >

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

        <xsl:param name="currentPage" />

        <!-- Grab a reference to the site's root -->
        <xsl:variable name="siteRoot" select="$currentPage/ancestor-or-self::*[@level = 1]" />

        <!-- Point to the two "roots" relative to the $siteRoot -->
        <xsl:variable name="authorsRoot" select="$siteRoot/../centreAuthors" />
        <xsl:variable name="pubRoot" select="$siteRoot/publicationHome" />
        <xsl:variable name="selectedAuthor" select="umb:RequestQueryString('author')"/>
       
        <xsl:template match="/">
                <xsl:apply-templates select="$authorsRoot/centreAuthor" />
        </xsl:template>

        <!-- Template for an author -->
        <xsl:template match="centreAuthor">
            <xsl:variable name="authorID" select="$selectedAuthor" />
            <h2>All Publications for <xsl:value-of select="@nodeName" /></h2>
            <ul>
                <xsl:apply-templates select="$pubRoot/publication[umb:Split(centreAuthors, ',')/value = $authorID]" /></ul>
        </xsl:template>

        <!-- Template for a publication -->
        <xsl:template match="publication">
            <li><a href="{umb:NiceUrl(@id)}"><xsl:value-of select="@nodeName" /></a></li>
            <xsl:if test="not(position() = last())"></xsl:if>
        </xsl:template>


    </xsl:stylesheet>
  • Chriztian Steinmeier 2798 posts 8787 karma points MVP 7x admin c-trib
    Jul 07, 2014 @ 15:31
    Chriztian Steinmeier
    0

    Hi Tom,

    If I understand correctly, you need to tweak it like this:

    • Leave the centreAuthor template as it was (setting the authorID variable equal to the @id of the node)
    • Change the root template (match="/") to only show the selected author:

      <xsl:template match="/">
          <ul>
              <xsl:apply-templates select="$authorsRoot/centreAuthor[@id = $selectedAuthor]" />
          </ul>
      </xsl:template>
      

    Was that the desired output?

    /Chriztian

  • Tom Cowling 144 posts 342 karma points
    Jul 07, 2014 @ 15:34
    Tom Cowling
    0

    Perfect! :D

     

Please Sign in or register to post replies

Write your reply to:

Draft