Copied to clipboard

Flag this post as spam?

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


  • Bjarne Fyrstenborg 1284 posts 4038 karma points MVP 8x c-trib
    Jan 09, 2012 @ 22:01
    Bjarne Fyrstenborg
    0

    Get image from child node

    Hi..

    I have done this the get the product image:

    <xsl:variable name="product" select="./ancestor-or-self::Product [last()]"/>
    <xsl:variable name="variants" select="$product/descendant-or-self::Product [not(child::Product)]"/>
    <xsl:variable name="variant" select="./descendant-or-self::Product [not(child::Product)][1]"/>
    <xsl:variable name="mediaImage" select="./productImage/DAMP/mediaItem[1]/Image" />
    <img src="{concat('/ImageGen.ashx?altImage=/gfx/no_image.gif&amp;Image=',$mediaImage/umbracoFile,'&amp;Width=',$imgWidth)}" class="productImage" alt="" />

    I want to change the mediaImage variable, so if the product node hasn't any image it should use the first child node image if it has one otherwise it can just set the variable to ./productImage/DAMP/mediaItem[1]/Image as imagegen then set an alternative empty image graphic.

    I have tried with this, but I get Error parsing XSLT file: \xslt\productList.xslt in frontend:

    <xsl:variable name="mediaImage">
              <xsl:choose>
              <xsl:when test="$product/productImage != ''">
                <xsl:text>./productImage/DAMP/mediaItem[1]/Image</xsl:text>
              </xsl:when>
              <xsl:when test="$variant/productImage != ''">
                <xsl:text>$variant/productImage/DAMP/mediaItem[1]/Image</xsl:text>
              </xsl:when>
              <xsl:otherwise>
                <xsl:text>./productImage/DAMP/mediaItem[1]/Image</xsl:text>
              </xsl:otherwise>
              </xsl:choose>
    </xsl:variable>

    Bjarne

     

  • Jan Skovgaard 11280 posts 23678 karma points MVP 11x admin c-trib
    Jan 09, 2012 @ 22:10
    Jan Skovgaard
    0

    Hi Bjarne

    I don't know if you are aware that by adding ?umbdebugshowtrace=1 or &umbdebugshowtrace=1 (if there are more parameters in the query) you can get a stack trace where you can sometimes can see a more descriptive error message marked in red text. If not, now you know - otherwise, nevermind :)

    I think that the problem above is that you're just setting the variable to have values like ./productImage/DAMP/mediaItem[1]/Image instead of actually getting the correct image path in the variable.

    If I have understood the above correctly you should use <xsl:value-of select="./productImage/DAMP/mediaItem[1]/Image" />, which should give you the image path in the variable instead.

    Hope this helps.

    /Jan

  • Bjarne Fyrstenborg 1284 posts 4038 karma points MVP 8x c-trib
    Jan 09, 2012 @ 22:30
    Bjarne Fyrstenborg
    0

    Hi Jan..

    Yes, I know that function: http://sub.ak-security.dk/da/shop/brandmateriel.aspx?umbDebugShowTrace=true 
    Had an extension on that i Chrome, so it easy to get these querystrings added to the url.

    I use the variable without umbracoFile because I use umbracoHeight and umbracoWidth some times.. like: 
    <xsl:variable name="imageWidth" select="number($mediaImage/umbracoWidth)"/>
    <xsl:variable name="imageHeight" select="number($mediaImage/umbracoHeight)"/>

    and just set the $mediaImage/umbracoFile inside img src attribute.

    I have also tried with value-of , but it doesn't seem to fix it.. I think I'll get the path to image inclusive size, height, width.. and set the variable to that.

    I'm not sure if I perhaps get more than only the string I want..

    Bjarne

  • Bjarne Fyrstenborg 1284 posts 4038 karma points MVP 8x c-trib
    Jan 09, 2012 @ 22:34
    Bjarne Fyrstenborg
    0

    I have changed the variable to the one I used before and instead called the variable testImage.. and the I get the output to see what I get:

    http://sub.ak-security.dk/da/shop/brandmateriel.aspx

    It gives me something like /media/1496/Pulverslukker 2 kg..jpg777946293388jpg , which seem to be fine .. when you get use /Image
    But does it then set /media/1496/Pulverslukker 2 kg..jpg777946293388jpg to the variable value instead of ./productImage/DAMP/mediaItem[1]/Image ?

    Because when I use this instead of the origianal mediaImage variable I also get the same error:

    <xsl:variable name="mediaImage">
    <xsl:value-of select="./productImage/DAMP/mediaItem[1]/Image" />
    </xsl:variable>

    Shouldn't that be the same as <xsl:variable name="mediaImage" select="./productImage/DAMP/mediaItem[1]/Image" /> ?

    Bjarne

  • Jan Skovgaard 11280 posts 23678 karma points MVP 11x admin c-trib
    Jan 09, 2012 @ 23:24
    Jan Skovgaard
    1

    Hi Bjarne

    Yes that expression should do the same.

    But don't you get any explanation in the stack trace that is of use? Maybe you need to wrap a <xsl:if> around your code somewhere to make sure it's not because of empty values getting passed that makes it all fail.

    /Jan

  • Bjarne Fyrstenborg 1284 posts 4038 karma points MVP 8x c-trib
    Jan 09, 2012 @ 23:29
    Bjarne Fyrstenborg
    0

    Yes.. then I think it's a bit strange that it works with <xsl:variable name="mediaImage" select="./productImage/DAMP/mediaItem[1]/Image" /> but not 

    <xsl:variable name="mediaImage">
     <xsl:value-of select="./productImage/DAMP/mediaItem[1]/Image" />
    </xsl:variable>

    I get this error:

    To use a result tree fragment in a path expression, first convert it to a node-set using the msxsl:node-set() function.
    To use a result tree fragment in a path expression, first convert it to a node-set using the msxsl:node-set() function.
      at System.Xml.Xsl.Runtime.XsltConvert.EnsureNodeSet(IList`1 listItems)
      at System.Xml.Xsl.CompiledQuery.Query.<xsl:template match="Product">(XmlQueryRuntime {urn:schemas-microsoft-com:xslt-debug}runtime, XPathNavigator {urn:schemas-microsoft-com:xslt-debug}current, Double {urn:schemas-microsoft-com:xslt-debug}position, Double {urn:schemas-microsoft-com:xslt-debug}last, IList`1 {urn:schemas-microsoft-com:xslt-debug}namespaces) in D:\hshome\steffenager\sub.ak-security.dk\xslt\productList_product.xslt:line 116
      at System.Xml.Xsl.CompiledQuery.Query.<xsl:apply-templates>(XmlQueryRuntime {urn:schemas-microsoft-com:xslt-debug}runtime, XPathNavigator , Double , Double )
      at System.Xml.Xsl.CompiledQuery.Query.<xsl:template match="/">(XmlQueryRuntime {urn:schemas-microsoft-com:xslt-debug}runtime, XPathNavigator {urn:schemas-microsoft-com:xslt-debug}current, Double {urn:schemas-microsoft-com:xslt-debug}position, Double {urn:schemas-microsoft-com:xslt-debug}last, IList`1 {urn:schemas-microsoft-com:xslt-debug}namespaces) in D:\hshome\steffenager\sub.ak-security.dk\xslt\productList.xslt:line 86
      at System.Xml.Xsl.CompiledQuery.Query.<xsl:apply-templates>(XmlQueryRuntime {urn:schemas-microsoft-com:xslt-debug}runtime, XPathNavigator , Double , Double )
      at System.Xml.Xsl.CompiledQuery.Query.Root(XmlQueryRuntime {urn:schemas-microsoft-com:xslt-debug}runtime)
      at System.Xml.Xsl.CompiledQuery.Query.Execute(XmlQueryRuntime {urn:schemas-microsoft-com:xslt-debug}runtime)
      at System.Xml.Xsl.XmlILCommand.Execute(Object defaultDocument, XmlResolver dataSources, XsltArgumentList argumentList, XmlSequenceWriter results)
      at System.Xml.Xsl.XmlILCommand.Execute(Object defaultDocument, XmlResolver dataSources, XsltArgumentList argumentList, XmlWriter writer)
      at System.Xml.Xsl.XslCompiledTransform.Transform(IXPathNavigable input, XsltArgumentList arguments, XmlWriter results, XmlResolver documentResolver)
      at System.Xml.Xsl.XslCompiledTransform.Transform(IXPathNavigable input, XsltArgumentList arguments, TextWriter results)
      at umbraco.macro.GetXsltTransformResult(XmlDocument macroXML, XslCompiledTransform xslt, Dictionary`2 parameters)
      at umbraco.macro.loadMacroXSLT(macro macro, MacroModel model, Hashtable pageElements)

    Bjarne

  • Jan Skovgaard 11280 posts 23678 karma points MVP 11x admin c-trib
    Jan 09, 2012 @ 23:35
    Jan Skovgaard
    2

    Hi Bjarne

    Aaah, does the variable return xml? What does the output look like if you write <xmp><xsl:copy-of select="$mediaImage" /></xmp> ?

    If so you'll need to use msxsl:node-set($mediaImage) because you're getting a set of xml nodes returned.

    Be aware that you need to add the namespace in the xsl:stylesheet part like: xmlns:msxsl="urn:schemas-microsoft-com:xslt".

    Hope this helps.

    /Jan

  • Bjarne Fyrstenborg 1284 posts 4038 karma points MVP 8x c-trib
    Jan 09, 2012 @ 23:44
    Bjarne Fyrstenborg
    0

    I get the image path as with value-of .. something like: /media/1443/Brandtæppe.jpg982114117jpg

    But I see that on the product " CO2 slukker " here: http://sub.ak-security.dk/da/shop/brandmateriel.aspx it doesn't return anything..

    Bjarne

  • Bjarne Fyrstenborg 1284 posts 4038 karma points MVP 8x c-trib
    Jan 10, 2012 @ 16:41
    Bjarne Fyrstenborg
    0

    Why is it the code below fails, when it works with <xsl:variable name="mediaImage" select="./productImage/DAMP/mediaItem[1]/Image" /> ?

    <xsl:variable name="mediaImage">
     <xsl:value-of select="./productImage/DAMP/mediaItem[1]/Image" />
    </xsl:variable>

    I think it might be the same reason why the variable I try to create not is working..

    Bjarne

  • Tom Fulton 2030 posts 4998 karma points c-trib
    Jan 10, 2012 @ 19:50
    Tom Fulton
    2

    Hi Bjarne,

    As Jan stated you need to use the msxml:node-set() function.  When you copy XML into a variable, it's no longer recognized as a "node-set" that you can run xpath queries on.  You need to use msxml:node-set() to turn it back into one.

    Ex:

    <xsl:variable name="mediaImage"><xsl:copy-of select="./productImage/DAMP/mediaItem[1]/Image"/></xsl:variable>
    <img src="{concat('/ImageGen.ashx?altImage=/gfx/no_image.gif&amp;Image=',msxml:node-set($mediaImage)/*/umbracoFile,'&amp;Width=',$imgWidth)}" class="productImage" alt="" />

    But if all you need is the umbracoFile there isn't really a need to do this, just store the umbracoFile in the variable

    <xsl:variable name="mediaImage"><xsl:value-of select="./productImage/DAMP/mediaItem[1]/Image/umbracoFile"/></xsl:variable>
    <img src="{concat('/ImageGen.ashx?altImage=/gfx/no_image.gif&amp;Image=',umbracoFile,'&amp;Width=',$imgWidth)}" class="productImage" alt="" />

    Also if you do end up using the first method and you need to re-use the variable, I commonly do something like this:

    <xsl:variable name="mediaImage"><xsl:copy-of select="./productImage/DAMP/mediaItem[1]/Image"/></xsl:variable>
    <xsl:variable name="mediaImageXml" select="msxml:node-set($mediaImage)/*" />

    Then you can reference $mediaImageXml instead of $mediaImage.

    -Tom

  • Bjarne Fyrstenborg 1284 posts 4038 karma points MVP 8x c-trib
    Jan 10, 2012 @ 20:42
    Bjarne Fyrstenborg
    0

    Hi Tom

    So when I used <xsl:copy-of ... to see what I had and it returned something like /media/1443/Brandtæppe.jpg982114117jpg or an empty string, it was actually in xml?

    What is the difference in using value-of and copy-of? Is copy-of just used when you want the xml?
    I prefer the last code example as I refer to umbracoHeight and umbracoWidth.. so I can use the variable there too..

     I have tried with this code:

    <xsl:variable name="testImage">
     <!--<xsl:copy-of select="./productImage/DAMP/mediaItem[1]/Image"/>-->
     <xsl:choose>
       <xsl:when test="./productImage != ''">
          <xsl:copy-of select="$product/productImage/DAMP/mediaItem[1]/Image"/>
       </xsl:when>
       <xsl:when test="$variant/productImage != ''">
          <xsl:copy-of select="$variant/productImage/DAMP/mediaItem[1]/Image"/>
       </xsl:when>
       <xsl:otherwise>
          <xsl:copy-of select="./productImage/DAMP/mediaItem[1]/Image"/>
       </xsl:otherwise>
     </xsl:choose>
    </xsl:variable>
            
    <xsl:variable name="mediaImage" select="msxml:node-set($testImage)/*"/>
    <xsl:variable name="imageWidth" select="number($mediaImage/umbracoWidth)"/>
    <xsl:variable name="imageHeight" select="number($mediaImage/umbracoHeight)"/>
    <img src="{concat('/ImageGen.ashx?altImage=/gfx/no_image.gif&amp;Image=',$mediaImage/umbracoFile,'&amp;Width=',$imgWidth)}" class="productImage" alt="{$productName}" title="{$productName}" width="{$imgWidth}" height="{$imgHeight}" />
    

    Then I have some variables $imgHeight and $imgWidth to calculate the height and width from the original sizes.
    When I use value-of it doesn't return the images, because it is in xml I think.. but when I use copy-of as above I now get the variant image. E.g. the product "Ildslukker 2 kg" here
     http://sub.ak-security.dk/da/shop/brandmateriel.aspx hasn't any image on the product node, but one on each of the two children. In Tea Commerce it show the first child node info instead of the product node, when it has variants.. 

    so now I can add images to the product node which it use.. otherwise the first child node image.. 

    Thanks for your help Tom ... again :)

    Bjarne

  • Jan Skovgaard 11280 posts 23678 karma points MVP 11x admin c-trib
    Jan 10, 2012 @ 21:20
    Jan Skovgaard
    0

    Hi Bjarne

    Glad to see you got this solved.

    xsl:copy-of should be used when you want to see and generate XML nodes. When you have a variable containing XML you can see the structure by writing it out in a <textarea></textarea> or <xmp</xmp> to see the structure so you can get an idea on how to match the nodes.

    value-of simply gives you the value of the whole nodeset as a string, which is pretty hard to parse and select the parts that you really need.

    If you had done a view source when you just made the xsl:copy-of you would have seen that there was XML elements written in the source. That's why it's a good idea to do as explained above - then it's also easy to copy the xml to a proper editor where you can get a better view of the returned XML structure.

    Hope this makes sense :)

    /Jan

  • Bjarne Fyrstenborg 1284 posts 4038 karma points MVP 8x c-trib
    Jan 10, 2012 @ 21:42
    Bjarne Fyrstenborg
    0

    Hi Jan

    Thanks for the explantion..

    When I previously used <xmp><xsl:copy-of select="$mediaImage" /></xmp> or  <textarea><xsl:copy-of select="$mediaImage" /></textarea> as you suggested it returned an empty string or something like /media/1443/Brandtæppe.jpg982114117jpg .. so I think it was hard to see it was the xml it returned..
    when I used:

    <xsl:variable name="mediaImage">
              <xsl:choose>
              <xsl:when test="$product/productImage != ''">
                <xsl:value-of select="./productImage/DAMP/mediaItem[1]/Image"/>
              </xsl:when>
              <xsl:when test="$variant/productImage != ''">
                <xsl:value-of select="$variant/productImage/DAMP/mediaItem[1]/Image"/>
              </xsl:when>
              <xsl:otherwise>
                <xsl:value-of select="./productImage/DAMP/mediaItem[1]/Image"/>
              </xsl:otherwise>
              </xsl:choose>
    </xsl:variable>
    sometimes I had used this trick before it has returned something with the start and end tags like in /App_Data/umbraco.config document.. 
    but also when change the variable from this:

    <xsl:variable name="mediaImage" select="./productImage/DAMP/mediaItem[1]/Image"/>
    to this:
    <xsl:variable name="mediaImage">
    <xsl:value-of select="./productImage/DAMP/mediaItem[1]/Image"/>
    </xsl:variable> 
    it failed.. so I guess it also should be changed to a node-set to work..?
    But it works with the variable I had made.. I should just use copy-of instead of value-of there.. and then change it back to a node-set.
    Bjarne

     

Please Sign in or register to post replies

Write your reply to:

Draft