Copied to clipboard

Flag this post as spam?

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


  • jacob phillips 130 posts 372 karma points
    Nov 19, 2012 @ 23:02
    jacob phillips
    0

    for loops, variable xpath selector, converting to newer schema

    I've been stuck on this for a while. I'm rewriting an XSLT written against the old schema. Let's call it "FeaturedContent.xslt". This particular XSLT displays content selected from different content pickers placed on document types all throughout a site. The content picker alias (now a MultiNodePicker alias in newer Umbraco version)  and its selected nodes used to be stored as XML attributes of an XML node, but now everything is stored in separate XML nodes (seems to make more sense.) The alias for the MultiNodePicker (MNP) is passed in via a macro parameter and stored in a variable called "position".

    What I want to be able to do is have my XPATH selector select the MultiNodePicker-picked nodes based on this "position" variable that gets passed in as a macro parameter. The string value will always match the name of the MultiNodePicker.

    Let's say my MNP is called "MNPLatestNews", normally, I could just loop through it's nodes, like this

     

    <xsl:for-each select="$currentPage/MNPLatestNews/MultiNodePicker/nodeId">

    But I want to do it in general, like this:

    <xsl:for-each select="$currentPage/$position/MultiNodePicker//nodeId">

    ...

    That's not going to work I guess because I can't use a variable after the first one in an XPATH selector?

     

    I've tried a number of different approaches. The one I would like to get working sets the XPATH selector in a global variable, like this:

        <xsl:variable name="nodes">
                <xsl:value-of select="$currentPage" />
                <xsl:value-of select="$position/MultiNodePicker/nodeId" />
        </xsl:variable>

     

    Then I can use it like this:

    <xsl:for-each select="msxsl:node-set($nodes)">
        <xsl:variable name="currentNode" select="umbraco.library:GetXmlNodeById(.)" />
    do some stuff here
    </xsl:for-each>

    But I just get an error when rendering (the XSLT editor save it w/no error though).

    Next I tried setting my variable a little differently:

    <xsl:variable name="nodes">
    <xsl:if test="$position != ''">
    <xsl:choose>
    <xsl:when test="$position = 'MNPLatestNews'">
    <xsl:value-of select="$currentPage/MNPLatestNews/MultiNodePicker/nodeId" />
    </xsl:when>
    </xsl:choose>
    </xsl:if>
    </xsl:variable>

     

    This sort of works, except that my for loop then only prints out the LAST node stored in my MultiNodePicker. Also, I don't really want to do it this way because then every time a add a new MNP to a docType, I'll have to come in and edit this macro if I want to use it on different templates.

    In the old XLST, it worked like this: The alias was used to get a comma separated list of node ids, then they were split and looped through. 

    <xsl:variable name="nodes" select="$currentPage/data[@alias=$position]"/>
    <xsl:variable name="splitNodes" select="umbraco.library:Split($nodes, ',')" />
    <xsl:for-each select="$splitNodes/value">
    ...

     

    I just want to adapt the existing XSLT as quickly as possible and move on. Here's the old XSLT

     

    <?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" xmlns:umbraco.contour="urn:umbraco.contour" xmlns:Designit.VideoEmbed="urn:Designit.VideoEmbed"
        exclude-result-prefixes="msxml umbraco.library Exslt.ExsltCommon Exslt.ExsltDatesAndTimes Exslt.ExsltMath Exslt.ExsltRegularExpressions Exslt.ExsltStrings Exslt.ExsltSets umbraco.contour Designit.VideoEmbed ">

      <xsl:include href="cprGetPrimaryImage.xslt" />
      <xsl:output method="xml" omit-xml-declaration="yes"/>

      <xsl:param name="currentPage"/>
      <xsl:variable name="featureOn" select="//macro/featureOn"/>
      <xsl:variable name="featureSize" select="//macro/featureSize"/>
      <xsl:variable name="position" select="//macro/position"/>
      <xsl:variable name="numberToDisplay" select="//macro/numberToDisplay"/>
      <xsl:variable name="numberLinksToDisplay" select="//macro/numberLinksToDisplay"/>
      <xsl:variable name="displayImage" select="//macro/displayImage"/>
      <xsl:variable name="useArchiveDate" select="//macro/useArchiveDate"/>
      <xsl:variable name="archiveOnly" select="//macro/archiveOnly"/>
      <xsl:variable name="featureTitle" select="//macro/featureTitle"/>
      <xsl:variable name="rssCount" select="//macro/rssCount"/>
      <xsl:variable name="titleColor" select="//macro/titleColor"/>

      <xsl:variable name="headerColorClass">
        <xsl:text>headerColor</xsl:text>
        <xsl:value-of select="$featureOn" />
      </xsl:variable>

      <xsl:variable name="pagePosition">
        <xsl:text>cprFeatures</xsl:text>
        <xsl:value-of select="$featureOn" />
      </xsl:variable>

      <xsl:variable name="addedLinks">

        <!-- View All Link -->
        <xsl:value-of select="'&lt;a class=&quot;all&quot; href=&quot;'" />
        <xsl:value-of select="'/viewAll.aspx?p&#61;'" />
        <xsl:value-of select="$featureOn" />
        <xsl:value-of select="'&amp;t&#61;'" />
        <xsl:value-of select="$featureTitle" />
        <xsl:value-of select="'&amp;pid&#61;'" />
        <xsl:value-of select="$currentPage/@id" />
        <xsl:value-of select="'&amp;s&#61;'" />
        <xsl:value-of select="$position" />
        <xsl:value-of select="'&amp;i&#61;'" />
        <xsl:value-of select="$displayImage" />
       <!-- The view recent feature has been discontinued. See source control for how this section is edited -->
       <xsl:value-of select="'&quot; title=&quot;View All Latest News section&quot;&gt;&lt;/a&gt;'" />


        <!-- RSS Link -->


        <xsl:value-of select="'&lt;a class=&quot;rss&quot; href=&quot;'" />
        <xsl:value-of select="'/rss.aspx?p&#61;'" />
        <xsl:value-of select="$featureOn" />
        <xsl:value-of select="'&amp;t&#61;'" />
        <xsl:value-of select="$featureTitle" />
        <xsl:value-of select="'&amp;pid&#61;'" />
        <xsl:value-of select="$currentPage/@id" />
        <xsl:value-of select="'&amp;s&#61;'" />
        <xsl:value-of select="$position" />
        <xsl:value-of select="'&amp;n&#61;'" />
        <xsl:value-of select="$rssCount" />


     
    <xsl:choose>
    <xsl:when test="$rssCount &gt; 0">
    <xsl:value-of select="'&quot; title=&quot;&quot; border=&quot;0&quot; src=&quot;&quot; /&gt;&lt;span&gt;&#160;&lt;/span&gt;&lt;span&gt;&#160;&lt;/span&gt;&lt;/a&gt;'" />
    </xsl:when>
    <xsl:otherwise>
    <xsl:value-of select="'&quot; title=&quot;&quot; border=&quot;0&quot; src=&quot;&quot; /&gt;&lt;/a&gt;'" />
    </xsl:otherwise>
    </xsl:choose>

      </xsl:variable>

      <xsl:template match="/">

        <!-- start writing XSLT -->

        <xsl:variable name="nodes" select="$currentPage/data[@alias=$position]"/>
        <xsl:variable name="splitNodes" select="umbraco.library:Split($nodes, ',')" />

        <xsl:if test="$nodes != ''">
          <div class="latest-news">
            <xsl:attribute name="class">
              <xsl:if test="$featureSize != 'Small'">news-latest</xsl:if>
         <xsl:choose>
                      <xsl:when test="$titleColor= '1'">
                        <xsl:value-of select="'-red'" />
                      </xsl:when>
                      <xsl:otherwise>
                        <xsl:value-of select="''" />
                      </xsl:otherwise>
            </xsl:choose>
            </xsl:attribute>

            <xsl:attribute name="id">
              <xsl:if test="$featureSize = 'Small'">community</xsl:if>
            </xsl:attribute>

            <xsl:if test="$featureTitle != ''">
              <div class="head {$headerColorClass} with-rss">
                <h3>
                  <xsl:value-of select="$featureTitle" disable-output-escaping="yes"/>
                </h3>
                <xsl:value-of select="$addedLinks" disable-output-escaping="yes"/>
              </div>
            </xsl:if>

            <ul>
              <xsl:for-each select="$splitNodes/value">
                <xsl:if test="$numberToDisplay >= position()">
            <div style="clear:both">
                  <xsl:variable name="currentNode" select="umbraco.library:GetXmlNodeById(.)" />

                  <xsl:variable name="atitle" select="$currentNode/@nodeName" />
                  <xsl:variable name="teaser" select="$currentNode/data [@alias = 'teaser']" />

                  <xsl:variable name="releaseDate" select="umbraco.library:FormatDateTime($currentNode/data [@alias = 'displayDate'], 'dddd, MMMM d, yyyy')" />

                  <xsl:variable name="externalUrl">
                    <xsl:choose>
                      <xsl:when test="string-length($currentNode/data [@alias = 'externalUrl']) != 0">
                        <xsl:value-of select="$currentNode/data [@alias = 'externalUrl']" />
                      </xsl:when>
                      <xsl:when test="string-length($currentNode/data [@alias = 'umbracoInternalRedirectId']) != 0">
                        <xsl:value-of select="$currentNode/data [@alias = 'umbracoInternalRedirectId']" />
                      </xsl:when>
                      <xsl:otherwise>
                        <xsl:value-of select="'none'" />
                      </xsl:otherwise>
                    </xsl:choose>
                  </xsl:variable>

                  <xsl:variable name="displayItem">
                    <xsl:if test="$useArchiveDate = 1">
                      <xsl:if test="$currentNode/data [@alias = 'archiveDate'] &gt; umbraco.library:CurrentDate()">
                        <xsl:value-of select="1" />
                      </xsl:if>
                      <xsl:if test="$currentNode/data [@alias = 'archiveDate'] &lt; umbraco.library:CurrentDate()">
                        <xsl:value-of select="0" />
                      </xsl:if>
                    </xsl:if>
                    <xsl:if test="$useArchiveDate = 0">
                      <xsl:if test="$archiveOnly = 1">
                        <xsl:if test="$currentNode/data [@alias = 'archiveDate'] &lt; umbraco.library:CurrentDate()">
                          <xsl:value-of select="1" />
                        </xsl:if>
                        <xsl:if test="$currentNode/data [@alias = 'archiveDate'] &gt; umbraco.library:CurrentDate()">
                          <xsl:value-of select="0" />
                        </xsl:if>
                      </xsl:if>
                    </xsl:if>
                    <xsl:if test="$useArchiveDate = 0 and $archiveOnly = 0">
                      <xsl:value-of select="1" />
                    </xsl:if>
                  </xsl:variable>


                  <xsl:if test="$displayItem = 1">
                    <xsl:variable name="imageSize">
                      <xsl:if test="$featureSize = 'ExtraLarge'">
                        <xsl:value-of select="'imageExtraLargeURL'" />
                      </xsl:if>
                      <xsl:if test="$featureSize = 'Large'">
                        <xsl:value-of select="'imageListLargeURL'" />
                      </xsl:if>
                      <xsl:if test="$featureSize = 'Medium'">
                        <xsl:value-of select="'imageListMediumURL'" />
                      </xsl:if>
                      <xsl:if test="$featureSize = 'Small'">
                        <xsl:value-of select="'imageListSmallURL'" />
                      </xsl:if>
                    </xsl:variable>

                    <xsl:choose>
                      <xsl:when test="$displayImage = '1'">

                        <li class="verbose">
                          <xsl:choose>
                            <xsl:when test="$externalUrl = 'none'">
                              <a class="image" href="{umbraco.library:NiceUrl($currentNode/@id)}" >
                                <xsl:call-template name="getprimaryimage">
                                  <xsl:with-param name="nodeid" select="$currentNode/@id" />
                                  <xsl:with-param name="imagetype" select="$imageSize" />
                                </xsl:call-template>
                              </a>
                            </xsl:when>
                            <xsl:otherwise>
                              <a class="image" href="{$externalUrl}" target="_blank">
                                <xsl:call-template name="getprimaryimage">
                                  <xsl:with-param name="nodeid" select="$currentNode/@id" />
                                  <xsl:with-param name="imagetype" select="$imageSize" />
                                </xsl:call-template>
                              </a>
                            </xsl:otherwise>
                          </xsl:choose>
                          <div class="description">
                            <xsl:choose>
                              <xsl:when test="$externalUrl = 'none'">
                                <h4>
                                  <a href="{umbraco.library:NiceUrl($currentNode/@id)}">
                                    <xsl:value-of select="$atitle" disable-output-escaping="yes" />
                                  </a>
                                </h4>
                              </xsl:when>
                              <xsl:otherwise>
                                <h4>
                                  <a href="{umbraco.library:NiceUrl($currentNode/@id)}" target="_blank">
                                    <xsl:value-of select="$atitle" disable-output-escaping="yes" />
                                  </a>
                                </h4>
                              </xsl:otherwise>
                            </xsl:choose>
                            <xsl:if test="$releaseDate != ''">
                              <em>
                                <xsl:value-of select="$releaseDate" disable-output-escaping="yes"/>
                              </em>
                            </xsl:if>
                            <div class="summary">
                              <p>
                                <xsl:value-of select="$teaser" disable-output-escaping="yes"/>
                              </p>
                            </div>
                            <!-- .summary -->
                          </div>
                          <!-- .description -->
                        </li>
                      </xsl:when>
                      <!-- .displayImage = 1 -->
                      <xsl:otherwise>
                        <li>
                          <xsl:choose>
                            <xsl:when test="$externalUrl = 'none'">
                              <h5>
                                <a href="{umbraco.library:NiceUrl($currentNode/@id)}">
                                  <xsl:value-of select="$atitle" disable-output-escaping="yes" />
                                </a>
                              </h5>
                            </xsl:when>
                            <xsl:otherwise>
                              <h5>
                                <a href="{umbraco.library:NiceUrl($currentNode/@id)}" target="_blank">
                                  <xsl:value-of select="$atitle" disable-output-escaping="yes" />
                                </a>
                              </h5>
                            </xsl:otherwise>
                          </xsl:choose>
                          <xsl:if test="$releaseDate != ''">
                            <em>
                              <xsl:value-of select="$releaseDate" disable-output-escaping="yes"/>
                            </em>
                          </xsl:if>
                        </li>
                      </xsl:otherwise>
                    </xsl:choose>

                  </xsl:if>
                  <!-- $displayItem = 1 -->
             </div>
                </xsl:if>
                <!-- $numberToDisplay >= position() -->
              </xsl:for-each>
            </ul>

          </div>
        </xsl:if>
        <!-- nodes != '' -->

      </xsl:template>

    </xsl:stylesheet>

     

     

  • Chriztian Steinmeier 2726 posts 8320 karma points MVP 4x admin c-trib
    Nov 19, 2012 @ 23:33
    Chriztian Steinmeier
    1

    Hi Jacob,

    You can use the name() function to select the Multi-Node Tree Picker property by name - like this:

    <xsl:variable name="nodes" select="$currentPage/*[name() = $position]/MultiPicker/nodeId" />

    Regarding the rest of the XSLT - I'd suggest you had a look at a couple of articles I wrote about using match templates and specifically using the Multi-Node Tree Picker .

    Using match templates is how XSLT actually works, and it will help you separate stuff, not having everything in one very long template... it's a totally different way of thinking though (compared to traditional programming languages), so may take a while to "grasp" fully if you haven't tried something like that before.

    /Chriztian

  • jacob phillips 130 posts 372 karma points
    Nov 20, 2012 @ 00:15
    jacob phillips
    0

    Thanks a bunch, and thanks for getting me started on some other approaches to for-each

  • 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