Copied to clipboard

Flag this post as spam?

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


  • Connie DeCinko 931 posts 1160 karma points
    Mar 11, 2011 @ 17:43
    Connie DeCinko
    0

    Conditional for-each?

    The code below works, but is bloated and full of redundancy.  How can I rewrite it, perhaps making the for-each statement (the only difference between the blocks) conditional?

          <xsl:choose>
            <xsl:when test="count(current()/child::* [@isDoc and string(umbracoNaviHide) != '1']) &gt; 0">
              <xsl:for-each select="$currentPage/self::* [@isDoc and string(umbracoNaviHide) != '1']">
                <h3>
                  <a href="{umbraco.library:NiceUrl(@id)}">
                    <xsl:value-of select="@nodeName"/>
                  </a>
                </h3>
              </xsl:for-each>
            </xsl:when>
            <xsl:otherwise>
              <xsl:for-each select="$currentPage/parent::* [@isDoc and string(umbracoNaviHide) != '1']">
                <h3>
                  <a href="{umbraco.library:NiceUrl(@id)}">
                    <xsl:value-of select="@nodeName"/>
                  </a>
                </h3>
              </xsl:for-each>
            </xsl:otherwise>
          </xsl:choose>
  • Tom Fulton 2030 posts 4998 karma points c-trib
    Mar 11, 2011 @ 17:54
    Tom Fulton
    0

    Hi Connie,

    One way would be to store the for-each xpath in a variable, not tested but something like this should work:

          
    <xsl:variable name="theItems">
    <xsl:choose>
            <xsl:when test="count(current()/child::* [@isDoc and string(umbracoNaviHide) != '1']) &gt; 0">
    <xsl:copy-of select="
    $currentPage/self::* [@isDoc and string(umbracoNaviHide) != '1']"/>
            </xsl:when>
            <xsl:otherwise>
    <xsl:copy-of select="
    $currentPage/parent::* [@isDoc and string(umbracoNaviHide) != '1']"/>
            </xsl:otherwise>
          </xsl:choose>
    </xsl:variable>

              <xsl:for-each select="$theItems">
                <h3>
                  <a href="{umbraco.library:NiceUrl(@id)}">
                    <xsl:value-of select="@nodeName"/>
                  </a>
                </h3>
              </xsl:for-each>

    And hopefully Chriztian will pop in and tell us the right way to do it with templates :)

    -Tom

  • Connie DeCinko 931 posts 1160 karma points
    Mar 11, 2011 @ 18:14
    Connie DeCinko
    0

    That's the same way I originally tried to do it, it makes sense when you look at it.  However, it saves but throws a parsing error when you run it.  My fear with templates is that again, I'll have to duplicate several dozen lines of code when only one line varies between them.

     

  • Tom Fulton 2030 posts 4998 karma points c-trib
    Mar 11, 2011 @ 18:26
    Tom Fulton
    0

    Just tried it, you might need to add this to the for-each (wouldn't save until I did)

      <xsl:for-each select="msxml:node-set($theItems)/*">

    Also is this block inside another for-each loop?  I assume it is since you reference current() in the first condition

    -Tom

  • Connie DeCinko 931 posts 1160 karma points
    Mar 11, 2011 @ 18:52
    Connie DeCinko
    0

    Yeah, that saves but still throws a parsing error.

    I found this reference which actually works, although a bit ugly.

        <xsl:variable name="startNode" select="($currentPage/self::* [@isDoc and string(umbracoNaviHide) != '1'])
          [count($currentPage/child::* [@isDoc and string(umbracoNaviHide) != '1']) &gt; 0] |
          ($currentPage/parent::* [@isDoc and string(umbracoNaviHide) != '1'])" />

    Problem now is I want to limit it to one level.  Gotta restrict my results / replace my for-each.

  • Connie DeCinko 931 posts 1160 karma points
    Mar 11, 2011 @ 22:44
    Connie DeCinko
    0

    Ok, I decided to try the template approach as it allows for passing in a paramater (learned something new).  I've almost got it, but still have two issues.  First, I can't seem to get a reference to a specific node (currently shown as //root).  Second, my test for child nodes appears hit and miss with the various methods I've tried.  Right now, if there are no children the check is not finding that.

    <?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"/>

    <xsl:template match="/">
      
      <xsl:if test="count($currentPage/ancestor-or-self::* [@template=1165 and string(umbracoNaviHide) != '1']) &gt; 0">

        <xsl:choose>
          <xsl:when test="$currentPage [name() = 'NewsRelease']">
            <xsl:call-template name="showMenu">
              <xsl:with-param name="startNode" select="//root"/>
            </xsl:call-template>
          </xsl:when>
          <!-- if node is a second level page, use self -->
          <xsl:when test="$currentPage [@isDoc and @level = 2 and string(umbracoNaviHide) != '1']">
            <xsl:call-template name="showMenu">
              <xsl:with-param name="startNode" select="$currentPage/self::*"/>
            </xsl:call-template>
          </xsl:when>
          <!-- check for children, only use self if node has children -->
          <xsl:when test="$currentPage/child::* [not(data[@alias = 'umbracoNaviHide'] = 1)]">
            <xsl:call-template name="showMenu">
              <xsl:with-param name="startNode" select="$currentPage/self::*"/>
            </xsl:call-template>
          </xsl:when>
          <!-- if no children, use parent -->
          <xsl:otherwise>
            <xsl:call-template name="showMenu">
              <xsl:with-param name="startNode" select="$currentPage/parent::*"/>
            </xsl:call-template>
          </xsl:otherwise>
        </xsl:choose>

      </xsl:if>

    </xsl:template>
        
    <xsl:template name="showMenu">
      <xsl:param name="startNode"/>

      <div class="block">

        <xsl:for-each select="$startNode [@isDoc and string(umbracoNaviHide) != '1']">
          <h3>
            <a href="{umbraco.library:NiceUrl(@id)}">
              <xsl:value-of select="@nodeName"/>
            </a>
          </h3>
        </xsl:for-each>
          
          <ul class="products">
            <xsl:for-each select="$startNode/* [@isDoc and string(umbracoNaviHide) != '1']">
              <xsl:variable name="subItems" select="umbraco.library:GetXmlNodeById(@id)/child::* [@isDoc and string(umbracoNaviHide) != '1']"/>
              <li>
                <xsl:if test="count($subItems)">
                  <xsl:attribute name="class">open</xsl:attribute>
                </xsl:if>
                <a href="{umbraco.library:NiceUrl(@id)}">
                  <xsl:value-of select="@nodeName"/>
                </a>
                <xsl:if test="count($subItems)">
                  <ul>
                    <xsl:for-each select="$subItems">
                      <xsl:variable name="subSubItems" select="umbraco.library:GetXmlNodeById(@id)/child::* [@isDoc and string(umbracoNaviHide) != '1']"/>
                      <li>
                        <a href="{umbraco.library:NiceUrl(@id)}">
                          <xsl:value-of  select="@nodeName"/>
                        </a>
                        <xsl:if test="count($subSubItems)">
                          <ul>
                            <xsl:for-each select="$subSubItems">
                              <li>
                                <a href="{umbraco.library:NiceUrl(@id)}">
                                  <xsl:value-of  select="@nodeName"/>
                                </a>
                              </li>
                            </xsl:for-each>
                          </ul>
                        </xsl:if>
                      </li>
                    </xsl:for-each>
                  </ul>
                </xsl:if>
              </li>
            </xsl:for-each>
          </ul>
        </div>
          </xsl:template>

    </xsl:stylesheet>
  • Chriztian Steinmeier 2800 posts 8791 karma points MVP 8x admin c-trib
    Mar 11, 2011 @ 22:52
    Chriztian Steinmeier
    0

    Hi Connie,

    The reason your "//root" doesn't work is because you're selecting it within the root ("/") template - in there, the / refers to a small <macro> XML document - you need to build the XPath off of $currentPage to do it - I usually do this right after the currentPage param:

    <xsl:param name="currentPage" />
    <xsl:variable name="root" select="$currentPage/ancestor-or-self::root" />

    I'll take a look at the rest and give you some hints to reduce it even further... 

    /Chriztian

  • Connie DeCinko 931 posts 1160 karma points
    Mar 11, 2011 @ 23:31
    Connie DeCinko
    0

    Ok, a bit closer.  Almost there...

    Got this to work, finally, for the child nodes:

    <xsl:when test="count($currentPage/descendant::* [@isDoc]) > 0">

    Now, I am using this temporarily, but need a correct solution to reference a specific node:

    <xsl:with-param name="startNode" select="$currentPage/../../../.."/>

     

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

    Continue discussion

Please Sign in or register to post replies