I have an XML feed data that I need to make into a link using XSL v1.0... this works, but the TYPE value needs to be in lower case for the link to work properly:
<a href="http://www.mysite.com/{TYPE}={ID}" target="_blank">
<img src="{IMAGE}" />
</a>
So, I tried doing this but it's giving me errors and I'm finding it difficult to trouble shoot as the error comes back as "XSLT compile error at (1,991). See InnerException for details." (the below is just a snippet).
<xsl:variable name="smallcase" select="'abcdefghijklmnopqrstuvwxyz'" />
<xsl:variable name="uppercase" select="'ABCDEFGHIJKLMNOPQRSTUVWXYZ'" />
<xsl:element name="a">
<xsl:attribute name="href">
<xsl:value-of select="concat('http://www.mysite.com/', translate(TYPE, $uppercase, $smallcase),'=',ID)"/>
</xsl:attribute>
<xsl:attribute name="target">
<xsl:text>_blank</xsl:text>
</xsl:attribute>
<xsl:text><img src="{IMAGE}" /></xsl:text>
</xsl:element>
Is there some blatantly obvious error there that I'm missing? Or maybe an easier method?
Much cleaner:
<a href="http://www.mysite.com/{translate(
TYPE,
$uppercase,
$smallcase)}={ID}"
target="_blank">
<img src="{IMAGE}" />
</a>
<xsl:text><img src="{IMAGE}" /></xsl:text>
should just be
<img src="{IMAGE}" />
Related
I am trying to retrieve the url to an image using the GetMedia mediapicker.
The code below works fine:
<xsl:for-each select="umbraco.library:GetXmlNodeById(1123)/* [#isDoc]">
<article>
<img width="1822" height="600">
<xsl:attribute name="src">
<xsl:value-of select="umbraco.library:GetMedia(1139, 0)/umbracoFile" />
</xsl:attribute>
</img>
<div class="contents">
<h1>
<xsl:value-of select="bannerHeading1"/>
</h1>
</div>
</article>
</xsl:for-each>
However, if I replace the key line with this:
<xsl:value-of select="umbraco.library:GetMedia(bannerImage, 0)/umbracoFile" />
I get a parsing error with the exception being an OverflowException (Value was either too large or too small for an Int32), which suggests that it's not the 1139 that is being passed in.
Is there a way I can pass in the property I want? The value of "bannerImage" is 1139 as I want it to be?
Thanks for any help.
Further: This is the XML structure being returned by GetXMLNodeById:
<?xml version="1.0" encoding="utf-8" ?>
<HomepageBanner id="1141" parentID="1123" level="3" writerID="0" creatorID="0" nodeType="1124" template="1125" sortOrder="0" createDate="2013-08-12T15:53:48" updateDate="2013-08-12T15:54:18" nodeName="Members" urlName="members" writerName="admin" creatorName="admin" path="-1,1065,1123,1141" isDoc="">
<bannerImage>1139</bannerImage>
<bannerHeading1>Members Area</bannerHeading1>
<bannerHeading2>..the place for all your needs</bannerHeading2>
</HomepageBanner>
For anyone else trying to get an image from an item in a content folder, this is how I got it to work:
<xsl:for-each select="umbraco.library:GetXmlNodeById(1123)/* [#isDoc]">
<article>
<!-- Store the ID -->
<xsl:variable name="mediaId" select="bannerImage" />
<!-- Check the ID is numeric -->
<xsl:if test="number($mediaId) > 0">
<xsl:variable name="mediaNode" select="umbraco.library:GetMedia($mediaId, false())" />
<xsl:if test="string-length($mediaNode/umbracoFile) > 0">
<img src="{$mediaNode/umbracoFile}" width="1822" height="600" />
<div class="contents">
<h1>
<xsl:value-of select="bannerHeading1"/>
</h1>
</div>
</xsl:if>
</xsl:if>
</article>
</xsl:for-each>
You first need to check that the value is numeric and then, the bit that was failing me, you need to add the "/umbracoFile" part to your media node variable.
Thanks to the contributors who helped me in the right direction.
I have a simple xsl file:
<xsl:for-each select="part">
<div class="part">
<h2>Part Name:<xsl:value-of select="#partName" /></h2>
<xsl:for-each select="input">
<p>
<input>
<xsl:attribute name="value">
<xsl:value-of select="." />
</xsl:attribute>
<xsl:attribute name="name"><xsl:value-of select="#inputName" /></xsl:attribute>
</input>
</p>
</xsl:for-each>
</div>
</xsl:for-each>
I want to save partname and use it latter. I tried as the following:
<xsl:for-each select="part">
<div class="part">
<h2>Part Name:<xsl:value-of select="#partName" /></h2>
**<xsl:param name="part_name"><xsl:value-of select="#partName" /></xsl:param>**
<xsl:for-each select="input">
<p>
<input>
<xsl:attribute name="value">
<xsl:value-of select="." />
</xsl:attribute>
<xsl:attribute name="name">**<xsl:value-of select="$part_name" />**-<xsl:value-of select="#inputName" /></xsl:attribute>
</input>
</p>
</xsl:for-each>
</div>
</xsl:for-each>
but it doesn't work. I don't know what should do.
You are probably getting the error Keyword xsl:param may not be used here.. This is because xsl:param should only really be found under the root xsl:stylesheet element, and are used for passing values from the external application.
What you need is xsl:variable in this case
<xsl:variable name="part_name">
<xsl:value-of select="#partName"/>
</xsl:variable>
Or simpler still....
<xsl:variable name="part_name" select="#partName"/>
In fact, you could do away with the variable altogether. Instead of doing this
<xsl:value-of select="$part_name"/>
You could just do this, to get the value from the parent element
<xsl:value-of select="../#part_name"/>
Do bear in mind, if you do use a variable, it will only be local to the scope of the xsl:for-each in this case.
I'm looking for some help with XSLT Tranforms.
I'm currently transforming links that match the format:
<link type="button" url="/page.html" text="Do something" />
By using the transform:
<xsl:template match="link">
<a target="_blank" href="{#url}" title="{#text}">
<xsl:if test="#type='button'">
<xsl:attribute name="class">btn</xsl:attribute>
</xsl:if>
<xsl:value-of select="#text" />
</a>
</xsl:template>
Which gives me the output:
<a class="btn" title="Do Something" href="/page.html" target="_blank">Do Something</a>
But now I'm looking to be able to detect when multiple links with the type "button" are grouped together like this:
<link type="button" url="/page.html" text="Do something" />
<link type="button" url="/page.html" text="Do something else" />
And output like so:
<ul class="btns">
<li>Do something</li>
<li>Do something else</li>
</ul>
Can anyone assist on this?
Thanks,
C.
The logic needs to go in the template for the parent of the link elements. Assuming you are using XSLT 2.0 it will be something like this:
<xsl:template match="parent">
<xsl:for-each-group select="*" group-adjacent="node-name()">
<xsl:choose>
<xsl:when test="self::link">
<ul>
<xsl:apply-templates select="current-group()"/>
</ul>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="current-group()"/>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each-group>
</xsl:template>
I'm wondering if there's a way to loop over a values specified in the XSL, rather than coming from the XML.
Let's say I have 3 possible checkboxes, with a "current" value that comes from the XML. I'd have an XML doc like
<rootNode>
<val>bar</val>
</rootNode>
and XSL code like
<input id="foo" type="checkbox" name="myvar" value="foo">
<xsl:if test="val='foo'">
<xsl:attribute name="checked">checked</xsl:attribute>
</xsl:if>
</input> <label for="foo">foo</label>
<input id="bar" type="checkbox" name="myvar" value="bar">
<xsl:if test="val='bar'">
<xsl:attribute name="checked">checked</xsl:attribute>
</xsl:if>
</input> <label for="bar">bar</label>
<input id="baz" type="checkbox" name="myvar" value="baz">
<xsl:if test="val='baz'">
<xsl:attribute name="checked">checked</xsl:attribute>
</xsl:if>
</input> <label for="baz">baz</label>
This works, but the XSL is very verbose. I'd LIKE to be able to do something like this:
<!-- this syntax doesn't work, is there something similar that does? -->
<xsl:variable name="boxNames" select="'foo','bar','baz'"/>
<xsl:for-each select="name in $boxNames">
<input id="{$name}" type="checkbox" name="myvar" value="{$name}">
<xsl:if test="val=$name">
<xsl:attribute name="checked">checked</xsl:attribute>
</xsl:if>
</input> <label for="{$name}"><xsl:value-of select="$name"/></label>
</xsl:for-each>
I can KIND OF get this by putting the code in a template and using multiple <call-template> <with-param> calls, but that's doesn't save much space over the original.
Is there any concise way to do this with XSL? I definitely can't put all the checkbox names in the XML output, it's a large list and unnecessarily bloats the XML.
Yes, you can get the source (!) of the XSL by calling the document('') function, which you can then use as node datasource.
<xsl:template name="boxNames"> <!-- not used as template -->
<name>foo</name>
<name>bar</name>
<name>baz</name>
</xsl:template>
[...]
<xsl:variable name="boxNames" select="document('')/xsl:stylesheet/xsl:template[#name='boxNames']/name" />
Try this, which is very close to the code you suggested:
<xsl:variable name="boxNames" select="'foo','bar','baz'"/>
<xsl:variable name="val" select="val"/>
<xsl:for-each select="$boxNames">
<input id="{.}" type="checkbox" name="myvar" value="{.}">
<xsl:if test="$val=.">
<xsl:attribute name="checked">checked</xsl:attribute>
</xsl:if>
</input> <label for="{.}"><xsl:value-of select="."/></label>
</xsl:for-each>
It needs an XSLT 2.0 processor though.
Template matches are effectively for-each loops.
<xsl:template match="/">
<xsl:apply-templates match="namespace:ItemName"/>
</xsl:template>
<xsl:template match="namespace:ItemName">
<input>
<xsl:attribute name="id"><xsl:value-of select="."></xsl:attribute>
<xsl:attribute name="type">checkbox</xsl:attribute>
<xsl:attribute name="name">myvar</xsl:attribute>
<xsl:attribute name="value"><xsl:value-of select="."></xsl:attribute>
<xsl:value-of select=".">
</input>
<label>
<xsl:attribute name="for"><xsl:value-of select="." /></xsl:attribute>
<xsl:value-of select="."/>
</label>
</xsl:template>
That should cut it down.
<a>
<xsl:attribute name="href">
<xsl:value-of select="link" />
</xsl:attribute>
<xsl:attribute name="target">new</xsl:attribute>
<xsl:value-of select="title" />
</a>
Thats my template, and in my code:
sb.Append("<title>");
sb.AppendFormat("{0} - {1}", f.UserName, f.PointTypeDesc);
sb.Append("</title>");
sb.Append("<link>");
sb.AppendFormat("{0}", HttpUtility.UrlEncode(url));
sb.Append("</link>");
url is "http://www.cnn.com"
But it renders as: "http://localhost/http://www.cnn.com"
any ideas?
It seems to me that the problem must be with HttpUtility.UrlEncode. Have you checked the contents of the xml that you're creating? The XSL looks correct to me, although it could be written more tersely as:
<a href="{#link}" target="new">
<xsl:value-of select="title"/>
</a>