Copied to clipboard

Flag this post as spam?

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


  • Neil 63 posts 105 karma points
    Nov 21, 2012 @ 04:49
    Neil
    0

    xslt parsing error for left nav on all pages after first node

    New to umbraco and xslt.  Built a simple site with both Home (and Home.master template) and ContentPage (and ContentPage.master template) document types based off of Page (and Site.master template) document type.  All non-home page nodes are of ContentPage document type.  Using a simple left nav based in xslt, the home page and the first node, the About page, the left nav looks fine. 

    For all other nodes in the left nav, when I go to those pages, the left nav shows an xslt parse error with the output from appending ?umbDebugShowTrace=true to the url showing this error:

    "Attribute and namespace nodes cannot be added to the parent element after a text, comment, pi, or sub-element node has already been added."

    I read that sometimes using preserve can have this effect, but that's not in my code.  Can anyone tell me what's wrong?  Here is the xslt code:

    <?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="L2" select="1"/>
      <xsl:variable name="L3" select="2"/>

      <xsl:template match="/">
        <!-- The fun starts here -->
        <p id="leftNav">
          <xsl:for-each select="$currentPage/ancestor-or-self::* [@level=$L2]/* [@isDoc and string(sideNavShow) = '1']">
              <xsl:if test="$currentPage/ancestor-or-self::* [@level]/@id = current()/@id">
                <xsl:attribute name="class">
                  <xsl:text>active</xsl:text>
                </xsl:attribute>
              </xsl:if>
            <xsl:choose>
              <xsl:when test="position() = last()">
                <br style="0.5em" />
              </xsl:when>
              <xsl:otherwise>
              </xsl:otherwise>
              </xsl:choose>
            <div>
              <a style="text-transform:uppercase;" href="{umbraco.library:NiceUrl(@id)}">
                <xsl:value-of select="@nodeName"/>
              </a><hr /></div><br />
          </xsl:for-each>
        </p>
      </xsl:template>
    </xsl:stylesheet>


  • Chriztian Steinmeier 2798 posts 8788 karma points MVP 7x admin c-trib
    Nov 21, 2012 @ 08:32
    Chriztian Steinmeier
    0

    Hi Neil,

    That error is happening because of the class="active" you're trying to set - if it's not executed ini the very first iteration of the loop, then you've already added text and/or child elements to the <p id="leftNav"> tag, and then you can't attach an attribute to it any longer — You'll need to do that before entering the for-each.

    Which one are you really trying to set the class on?

    /Chriztian

  • Neil 63 posts 105 karma points
    Nov 21, 2012 @ 14:44
    Neil
    0

    Hi Chriztian,

    I see!  I'm very new to xslt so I was just adapting the out-of-the-box LeftNav.xslt without digging into what was happening in each piece.  So, what I want is for that class="active" to be set for the current node I'm in.  It seems that it's setting it only for the first, so if I'm not in the first node, it fails.  Is that a correct interpretation?  If that's the case, though, then why does this test fail:

    <xsl:if test="$currentPage/ancestor-or-self::* [@level]/@id = current()/@id">

    ?

    At first glance, it looks to be the right test, doesn't it?

    Neil

  • Neil 63 posts 105 karma points
    Nov 21, 2012 @ 14:45
    Neil
    0

    Also, forgot to say that yes, removing that element entirely did get rid of the error, but I still want to add the class=active to the current node...

  • Neil 63 posts 105 karma points
    Nov 21, 2012 @ 17:14
    Neil
    0

    Okay, climbing the learning curve.  I see now that the <xsl:attribute> element refers to whatever element it sits underneath, adding the class="active" to that element's opening tag.  The reason my script was breaking was because it was trying to set the <p> tag to active for each node, but the <p> element encloses the entire nav list and so had already been set to active on the first pass.  I moved that attribute test to sit underneath the <a> tag, which is the element I want to be active, and now it works like a champ.

    Here's the change:

    <pid="leftNav">
         
    <xsl:for-eachselect="$currentPage/ancestor-or-self::* [@level=$L2]/* [@isDoc and string(sideNavShow) = '1']">
            <xsl:choose>
             
    <xsl:whentest="position() = last()">
               
    <brstyle="0.5em"/>
             
    </xsl:when>
             
    <xsl:otherwise>
             
    </xsl:otherwise>
             
    </xsl:choose>
           
    <div>
             
    <astyle="text-transform:uppercase;"href="{umbraco.library:NiceUrl(@id)}">
              <xsl:iftest="$currentPage/ancestor-or-self::* [@level]/@id = current()/@id">
               
    <xsl:attributename="class">
                 
    <xsl:text>active</xsl:text>
               
    </xsl:attribute>
             
    </xsl:if>
               
    <xsl:value-ofselect="@nodeName"/>
             
    </a><hr/></div><br/>
         
    </xsl:for-each>
       
    </p>

     

Please Sign in or register to post replies

Write your reply to:

Draft