Copied to clipboard

Flag this post as spam?

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


  • Laura Holland 82 posts 103 karma points
    Sep 23, 2009 @ 21:48
    Laura Holland
    0

    xslt macro for generating a list of articles, by category?

    Hello folks,

    I'm new at both XSLT and Umbraco, and I'm liking both so far. I am creating a macro to generate a listing of articles, by category, that are on the website. I created an article document type and added a checkbox list data type for the article author to check off the appropriate categories, no problem.  I was originally going to build an asp.net user control to generate the listing, but I found a snippet of XSLT somewhere on this forum (can't find it now) which does nearly what I need to do. I tweaked it a bit, and it works spendidly. My problem is that in my document type I created a checkbox list to mark the category of the article, and multiple categories can be selected, which messes things up.

    What I want is this, where "strawberry" is about both "Fruit" and "Red" categories:

    Fruit

    • blueberry
    • strawberry

    Red

    • strawberry

    What I currently get from the XSLT is this:

    Fruit

    • blueberry

    Fruit, Red

    • strawberry

    Can this be done with xslt?

    This is what I'm working with now, and it would work swimmingly if it weren't for the multiple values:

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE xsl:stylesheet [ <!ENTITY nbsp "&#x00A0;"> ]>
    <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"
        exclude-result-prefixes="msxml umbraco.library Exslt.ExsltCommon Exslt.ExsltDatesAndTimes Exslt.ExsltMath Exslt.ExsltRegularExpressions Exslt.ExsltStrings Exslt.ExsltSets ">

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

        <xsl:param name="currentPage"/>

        <!-- Input the documenttype you want here -->
        <xsl:variable name="documentTypeAlias" select="string('HVACRArticle')"/>
        <xsl:variable name="groupByAlias" select="string('ArticleType')"/>
        <xsl:variable name="listArticleTitle" select="string('ArticleTitle')"/>
        <xsl:variable name="data" select="umbraco.library:GetXmlAll()/descendant-or-self::node [@nodeTypeAlias = $documentTypeAlias and string(data [@alias='umbracoNaviHide']) != '1']"/>
        <xsl:key name="nodes-by-category" match="node" use="string(data [@alias='ArticleType'])"/>
        <!-- unfortuantely xsl:key does not accept variables so we have to repeat our field here -->

        <xsl:template match="/">

            <!-- by category -->
            <xsl:for-each select="$data[count(. | key('nodes-by-category', string(data [@alias=$groupByAlias]))[1]) = 1]">
                <xsl:sort select="string(data [@alias=$groupByAlias])" />
       

                <h3>
                    <xsl:value-of select="data [@alias=$groupByAlias]" />
                </h3>

                <div style="margin-bottom: 20px;">
                    <div class="itm">
                        <xsl:for-each select="key('nodes-by-category', string(data [@alias=$groupByAlias]))">
                            <xsl:sort select="@nodeName" />

                            <div class="title">
                               <a>
                 <xsl:attribute name="href">
            <xsl:value-of select="umbraco.library:NiceUrl(@id)"/>
                  </xsl:attribute>
            <xsl:value-of select="data [@alias=$listArticleTitle]" /></a>
                            </div>
                            </xsl:for-each>
                    </div>
                </div>
            </xsl:for-each>
        </xsl:template>

    </xsl:stylesheet>
  • Tommy Poulsen 514 posts 708 karma points
    Sep 23, 2009 @ 22:25
    Tommy Poulsen
    0

    Hi Laura, I have not had time to come up with some ingenious grouping xslt for handling your issue, but I just thought that maybe you should also consider using tags (theres a new tag datatype in v4) as your categories. There's an example here

    >Tommy

     

  • Laura Holland 82 posts 103 karma points
    Sep 23, 2009 @ 23:36
    Laura Holland
    0

    I was just looking at the tag datatype... When I add a tag section to my "articles" document type, it appears to want to add a list of links, which isn't really what I want. Maybe if I create a custom datatype using the tag functionality? I will try that..

  • Laura Holland 82 posts 103 karma points
    Oct 31, 2009 @ 03:20
    Laura Holland
    0

    Well, I ran into the same problem with the tags datatype as I did with my custom checkboxlist datatype, which is that my xslt code doesn't know how to handle nodes that have been assigned several tags or topics. Both the tag or checkboxlist datatype store the info in the db as a comma seperated list, so if I check off "fruit" and "red" it says "fruit,red" in the db. Has anyone successfully figured out what to do with datatypes that have multiple values?

  • Josh Townson 67 posts 162 karma points
    Oct 31, 2009 @ 12:04
    Josh Townson
    0

    Hi Laura, I think this is quite difficult to do in xslt.

    You seem to write your xslt quite differently to myself. I suspect yours is neater and better, and I might be way off in trying to help here...

    But you might get some mileage out of

    <xsl:variable name="categories" select="Exslt.ExsltStrings:split(data [@alias=$groupByAlias],',')"/>

    which will produce a node set somthing like:

    <token>fruit</token>
    <token>red</token>

    in the variable.

    If you are matching two different strins that can have multiple items; make such a variable for each umbraco node, then you can use another EXSLT function from the sets to check if they contain any of the same nodes:

    <xsl:variable name="categories" select="Exslt.ExsltStrings:split($currentPage/data[@alias='ArticleType'])"/>
    <xsl:for-each select="$data//node[@nodeTypeAlias=$documentTypeAlias]">
    <xsl:variable name="localCat" select="Exslt.ExsltStrings:split(./data [@alias=$groupByAlias],',')"/>
    <xsl:if test="Exslt.ExsltSets:hassamenode($localCat,$categories)">
    <!-- This will match all umbraco nodes which share a category from the ArticleType property (comma separated string) -->
    </xsl:if>
    </xsl:for-each>

    Hope you can work out something that works for you from this.

    Josh

Please Sign in or register to post replies

Write your reply to:

Draft