Copied to clipboard

Flag this post as spam?

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


  • Mads Sørensen 188 posts 433 karma points
    May 25, 2013 @ 00:15
    Mads Sørensen
    0

    Variable attribute

    Hey Guys
    I've a problem with collecting values in an variable with xsl:attribute.

    I'm getting this message:

    Error occured
    System.Xml.Xsl.XslTransformException: An item of type 'Attribute' cannot be constructed within a node of type 'Root'.

    <xsl:variable name="rootnode" select="$currentPage/ancestor-or-self::* [@level = '1']" />    
    <xsl:variable name="bgImage" select="$rootnode/backgroundPicker" />

    <xsl:variable name="selectedImage">
        <xsl:attribute name="select">
            <xsl:choose>
                <xsl:when test="$bgImage != ''"><xsl:value-of select="$bgImage" /></xsl:when>
                <xsl:otherwise>pick an item</xsl:otherwise>
            </xsl:choose>
        </xsl:attribute>
    </xsl:variable>

    <xsl:value-of select="$selectedImage" />


    Any ideas what i'm doing wrong?

     

  • Jan Skovgaard 11280 posts 23678 karma points MVP 11x admin c-trib
    May 25, 2013 @ 11:04
    Jan Skovgaard
    1

    Hi Mads

    <xsl:attribute> should be used to set an attribute on an elements. In the above you just need a value in the variable, which should either hold a path to an image or display a text.

    To set an attribute on an element you should do it like this for instance:

    <div>
    <xsl:attribute name="class">box</xsl:attribute>
    </div> 

    So just remove the attribute element in the above and your variable will work.

    Hope this helps.

    /Jan

  • Mads Sørensen 188 posts 433 karma points
    May 25, 2013 @ 12:01
    Mads Sørensen
    0

    Hey Jan
    I dont think i understand what you mean?

    What i want is something like this:

    <div id="holder" style="background: url({$bgImage})"></div>

    but i need to check what value i checked?

    And i wanted to use the variable insite the div style?

    I hope it make seense :)

  • Jan Skovgaard 11280 posts 23678 karma points MVP 11x admin c-trib
    May 25, 2013 @ 12:12
    Jan Skovgaard
    0

    Hi Mads

    Ok, to achieve the above you will need to do something like this.

     

    <xsl:variable name="rootnode" select="$currentPage/ancestor-or-self::* [@level = '1']" />

    <xsl:variable name="bgImage" select="$rootnode/backgroundPicker" />

     

    <div id="holder">

    <xsl:if test="normalize-space($bgImage)">
    <xsl:attribute name="style">

    <xsl:value-of select="concat('background: url',$bgImage,');')" />

    </xsl:attribute>
    </xsl:if>

    </div>

    This should do the trick if the bgImage is not empty. In the above I'm just asuming that an image has been uploaded directly on your root node. If you're using a media picker then you will of course need to use GetMedia to fetch the proper image from the chosen media id.

    Hope the above makes a bit more sense :)

    /Jan

     

  • Mads Sørensen 188 posts 433 karma points
    May 25, 2013 @ 12:21
    Mads Sørensen
    0

    Hej Jan
    I was just working out something simular. It's bit tricky solution, we are runne multiple sites on same umbraco install.

    And it's the same kind of clients but with custom themes to there websites.

    <xsl:variable name="rootnode" select="$currentPage/ancestor-or-self::* [@level = '1']" />   

    <xsl:variable name="bgImage" select="$rootnode/backgroundPicker" />

    <xsl:value-of select="$bgImage" />

    <div class="fullWidthWrapper" id="sliderBackground">
            <xsl:attribute name="style"><xsl:text>background: url(</xsl:text>
                    <xsl:choose>
                            <xsl:when test="$bgImage = 'Sortplade'">/images/patterns/blackplate.png</xsl:when>
                    </xsl:choose>
                    <xsl:text>);</xsl:text>
            </xsl:attribute>
    </div>

    I'll just need to apply xsl:otherwise as fallback :D

    Is it at stupid way to solve the problem? I'm not sure if it's the best way?

  • Jan Skovgaard 11280 posts 23678 karma points MVP 11x admin c-trib
    May 25, 2013 @ 13:03
    Jan Skovgaard
    1

    Hi Mads

    Hi Mads the above looks fine to me.

    Wether or not it's an ideal solution is hard for me to say since I only see the tip of the iceberg. But from what I've seen above I think it makes sense if you just don't do too much inline-styling. In situations where you need to be able to select backround images from a CMS then I think it's perfectly valid to use inline styling.

    Glad you figured it out btw :)

    /Jan

  • Chriztian Steinmeier 2800 posts 8790 karma points MVP 8x admin c-trib
    May 25, 2013 @ 13:16
    Chriztian Steinmeier
    2

    Hi Mads (+ Jan),

    If there's only a single (or maybe a couple) exception(s), I usually make the code reflect the common state, and then have a clear condition to handle the exception.

    So I'd throw the style attribute on, using an attribute value template (the curly braces) and then immediately after use an if + attribute instruction to override the style attribute if necessary:

    <xsl:variable name="rootnode" select="$currentPage/ancestor-or-self::* [@level = '1']" />    
    <xsl:variable name="bgImage" select="$rootnode/backgroundPicker" />
    
    <div class="fullWidthWrapper" id="sliderBackground" style="background: url({$bgImage});">
        <xsl:if test="$bgImage = 'Sortplade'">
            <xsl:attribute name="style">background: url(/images/patterns/blackplate.png);</xsl:attribute>
        </xsl:if>
        <!-- ... -->
    </div>
    

    /Chriztian

  • Mads Sørensen 188 posts 433 karma points
    May 25, 2013 @ 13:26
    Mads Sørensen
    0

    Hey guys.

    Thanks for your help Jan.

    Chriztian the problem is that the background picker at custom dropdown list with some options and not a image it self.
    But if I understand it right your will override the bgImage variable when your make the if statement? is that correct understod?

  • Mads Sørensen 188 posts 433 karma points
    May 25, 2013 @ 13:27
    Mads Sørensen
    0

    Another thing, i thought it was possible to make an attribute on af variable?

    Am i wrong on this?

  • Chriztian Steinmeier 2800 posts 8790 karma points MVP 8x admin c-trib
    May 25, 2013 @ 13:41
    Chriztian Steinmeier
    101

    Hi Mads,

    No - the $bgImage variable stays the same, but the style attribute will be overridden (which is probably also what you meant) - "There can only be one" (the Highlander rule :-) attribute of the name "style", so the last one added will be the one that ends up in the output tree.

    But now I get what you want - you need to map the values in your picker to actual images... check this out then:

    <xsl:variable name="rootnode" select="$currentPage/ancestor-or-self::* [@level = '1']" />
    
    <!-- Lookup variable for background images -->
    <xsl:variable name="imagesProxy">
        <bg id="SortPlade" src="/images/patterns/blackplate.png" />
        <bg id="GulPlade" src="/images/patterns/yellowplate.png" />
        <!-- etc. -->
    </xsl:variable>
    <xsl:variable name="images" select="msxml:node-set($imagesProxy)" />
    
    <!-- Find the image chosen in the picker (if any) -->
    <xsl:variable name="bgImage" select="$images/bg[@id = $rootnode/backgroundPicker]/@src" />
    
    <!-- Add a default (fallback) image directly -->
    <div class="fullWidthWrapper" id="sliderBackground" style="background: url(/images/patterns/default.png);">
        <!-- If an image was picked, use that instead -->
        <xsl:if test="normalize-space($bgImage)">
            <xsl:attribute name="style">
                <xsl:value-of select="concat('background: url(', $bgImage, ');')" />
            </xsl:attribute>
        </xsl:if>
        <!-- ... -->
    </div>
    

    /Chriztian

  • Mads Sørensen 188 posts 433 karma points
    May 26, 2013 @ 08:59
    Mads Sørensen
    0

    Hey Chriztian
    That works just as great as my own so let me se if get this right.



    <xsl:variablename="rootnode"select="$currentPage/ancestor-or-self::* [@level = '1']"/>

    <!-- This is a kind of the xsl:choose it looks for wich one i choosen? -->
    <xsl:variablename="imagesProxy">
           
    <bgid="SortPlade"src="/images/patterns/blackplate.png"/>
           
    <bgid="GulPlade"src="/images/patterns/yellowplate.png"/>
           
    <!-- etc. -->
    </xsl:variable>

    <!-- ...And then it does something i dont understand - msxml:node-set explanation??? -->
    <xsl:variablename="images"select="msxml:node-set($imagesProxy)"/>

    <!-- and then i catch the image from the imagesProxy -->
    <xsl:variable name="bgImage"select="$images/bg[@id = $rootnode/backgroundPicker]/@src"/>

    <!-- Add a default (fallback) image directly -->
    <divclass="fullWidthWrapper"id="sliderBackground"style="background: url(/images/patterns/default.png);">
           
    <!-- If an image was picked, use that instead -->
           
    <xsl:iftest="normalize-space($bgImage)">
                   
    <xsl:attributename="style">
     
     
    <!-- What does concat do? Is it way to insert plain text? -->
                           
    <xsl:value-ofselect="concat('background: url(', $bgImage, ');')"/>
                   
    </xsl:attribute>
           
    </xsl:if>
           
    <!-- ... -->
    </div>

     

           

    I know im a bit heavy to dance with :o)

    /mads

  • Chriztian Steinmeier 2800 posts 8790 karma points MVP 8x admin c-trib
    May 26, 2013 @ 22:40
    Chriztian Steinmeier
    0

    Hi Mads,

    I like that you're not just "OK, I'll copy & paste that here - next..." but (like me) actually want to know what's going on :-)

    The $imagesProxy variable is just a chunk of XML that we've constructed so it maps a value to an image. Unfortunately, you can't use XPath on a variable created like that because of (insert long difficult explanation here - google "Result Tree Fragment" if you're curious) - so that's why the msxml:node-set() function is there - it converts our XML variable into a nodeset, on which we can now use XPath, which we do to select the image that maps to the value that was selected in the backgroundPicker property on the $rootNode.

    concat() is a function that takes 2 or more arguments — converting every argument to a string and returning them as a single string - when used in a value-of instruction, it's essentially the same as using a mix of text and value-of instructions, e.g.:

    <xsl:text>Hello </xsl:text>
    <xsl:value-of select="$name" />
    <xsl:text>, how are you?</xsl:text>

    Is the same as:

    <xsl:value-of select="concat('Hello ', $name, ', how are you?')" />

    In most situations, using concat() is just easier to "read".

    Hope that clears some of your questions!

    /Chriztian

  • Mads Sørensen 188 posts 433 karma points
    May 27, 2013 @ 10:15
    Mads Sørensen
    0

    Hi Chriztian

    So basicly this is

    <xsl:variablename="imagesProxy">
           
    <bgid="SortPlade"src="/images/patterns/blackplate.png"/>
           
    <bgid="GulPlade"src="/images/patterns/yellowplate.png"/>
    </xsl:variable>

    <imagesProxy>
         <bg>    
              <id>SortPlate</id>
              <src>/images/....</src>
         </bg>
         <bg>    
              <id>YellowPlate</id>
              <src>/images/....</src>
         </bg>
    </imagesProxy>

    And then you tell umbraco that imagesproxy is a node like in the content tree with values of id and src??

  • Chriztian Steinmeier 2800 posts 8790 karma points MVP 8x admin c-trib
    May 28, 2013 @ 22:45
    Chriztian Steinmeier
    0

    Hi Mads,

    Yeah - that's basically it - you *could* actually define it like that (using <id> and <src> nodes instead of attributes) and then you would just have to remove the "@" where you select them (so $images[id = ...]/src instead of $images[@id = ...]/@src) - it's just a chunk of XML that you can use standard XPath on.

    /Chriztian

  • Mads Sørensen 188 posts 433 karma points
    May 29, 2013 @ 08:44
    Mads Sørensen
    0

    Hi Chriztian

    I think i get it :D

    I've already used it several times :D



  • Mads Sørensen 188 posts 433 karma points
    May 29, 2013 @ 14:48
    Mads Sørensen
    0

    Hi Chriztian

    ...and then i ran into this problem. It only output the first image??? what do i do wrong?

    <xsl:variable name="iconProxy">
    <icon id="Grill" src="/images/icon/icon_grill.png"/>
    <icon id="Kniv og gaffel" src="/images/icon/icon_knife_fork.png"/>
    </xsl:variable>
    <xsl:variable name="setIcon" select="msxml:node-set($iconProxy)" />

    <h1 style=" color: white;">
    <xsl:for-each select="$slideNode/Slide">

    <xsl:variable name="getImage" select="$setIcon/icon[@id = $slideNode/Slide/slideIcon]/@src" />

    <xsl:if test="slideIcon = $setIcon/icon/@id">
    <img>
    <xsl:attribute name="src">
    <xsl:value-of select="$getImage" />
    </xsl:attribute>
    </img>
    </xsl:if>

    <xsl:text> </xsl:text>
    </xsl:for-each>
    </h1>

  • Chriztian Steinmeier 2800 posts 8790 karma points MVP 8x admin c-trib
    May 29, 2013 @ 15:01
    Chriztian Steinmeier
    0

    Hi Mads,

    This happens because you're accidentally picking the first one everytime (because you're using $slideNode inside the for-each) - when you're inside a for each and you're doing a comparison this way, you need to use the current() function to get a reference to the current item in the loop:

    <xsl:for-each select="$slideNode/Slide">
        <xsl:variable name="getImage" select="$setIcon/icon[@id = current()/slideIcon]/@src" />
        <xsl:if test="slideIcon = $setIcon/icon/@id">
            <img src="{$getImage}" />
        </xsl:if>
        <xsl:text> </xsl:text>
    </xsl:for-each>

    /Chriztian

  • Chriztian Steinmeier 2800 posts 8790 karma points MVP 8x admin c-trib
    May 29, 2013 @ 15:04
    Chriztian Steinmeier
    0

    Oh - and by the way: I don't get what the xsl:if around the <img> is supposed to do, actually - was that an extra check you we're doing?

    Shouldn't be necessary...

    /Chriztian

  • Mads Sørensen 188 posts 433 karma points
    May 30, 2013 @ 21:42
    Mads Sørensen
    0

    Understanding the context I do master'xslt'jedi!
    - and it make sense :D

    Thanks a lot Chriztian :o)

Please Sign in or register to post replies

Write your reply to:

Draft