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:
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.
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..
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:
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.
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)
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.
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..
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" herehttp://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..
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.
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..
Get image from child node
Hi..
I have done this the get the product image:
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:
Bjarne
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
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
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:
Shouldn't that be the same as <xsl:variable name="mediaImage" select="./productImage/DAMP/mediaItem[1]/Image" /> ?
Bjarne
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
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
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
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
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
Why is it the code below fails, when it works with <xsl:variable name="mediaImage" select="./productImage/DAMP/mediaItem[1]/Image" /> ?
I think it might be the same reason why the variable I try to create not is working..
Bjarne
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:
But if all you need is the umbracoFile there isn't really a need to do this, just store the umbracoFile in the variable
Also if you do end up using the first method and you need to re-use the variable, I commonly do something like this:
Then you can reference $mediaImageXml instead of $mediaImage.
-Tom
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:
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
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
Hi Jan
Thanks for the explantion..
<xsl:variable name="mediaImage" select="./productImage/DAMP/mediaItem[1]/Image"/>
is working on a reply...