<xsl:for-eachselect="$currentPage/ancestor-or-self::* [@isDoc]/EventCalendar//* [name()='Event' and umbraco.library:DateGreaterThanOrEqualToday(./eventStartDateTime) and string(./umbracoNaviHide) != '1']">
It looks like your when condition doesn't check for umbracoNaviHide - I would just copy your xpath from the for-each into your when condition so they are both looking for the same thing.
I have the same in the when condition and for-each and seem to work now :)
<xsl:when test="$currentPage/ancestor-or-self::* [@isDoc]/EventCalendar//* [@isDoc and name()='Event' and umbraco.library:DateGreaterThanOrEqualToday(./eventStartDateTime) and string(./umbracoNaviHide) != '1']"> <ul class="events"> <xsl:for-each select="$currentPage/ancestor-or-self::* [@isDoc]/EventCalendar//* [@isDoc and name()='Event' and umbraco.library:DateGreaterThanOrEqualToday(./eventStartDateTime) and string(./umbracoNaviHide) != '1']"> .... </xsl:for-each> </ul> </xsl:when> <xsl:otherwise> <p>Der er i øjeblikket ingen kommende events.p> </xsl:otherwise> </xsl:choose>
Ooops - looks like I forgot to change the level for the root - it should be 1:
<!-- Site root -->
<xsl:variable name="siteRoot" select="$currentPage/ancestor-or-self::*[@level = 1]" />
<!-- Grab the calendar root -->
<xsl:variable name="calendarRoot"select="$siteRoot/*[@nodeName = 'Aktuelt']/EventCalendar"/>
<!-- Get any future events -->
<xsl:variable name="futureEvents" select="$calendarRoot//Event[not(umbracoNaviHide = 1)][umbraco.library:DateGreaterThanOrEqualToday(eventStartDateTime)]" />
Also - (as noted above) you should really test for umbracoNaviHide first, so you're not calling the DateGreaterThanOrEqualToday() function for any hidden nodes.
Okay, it worked before with string(./umbracoNaviHide) != '1'] but it is probably unnessary to calling DateGreaterThanOrEqualToday() function, when the node is hidden..
But when I use it in my calendarRoot variable I get this xslt error: <xsl:variable name="calendarRoot" select="$siteRoot/*[@nodeName = 'Aktuelt']/EventCalendar"/>
Error occured
System.OverflowException: Value was either too large or too small for an Int32. at System.Convert.ToInt32(Double value) at System.Convert.ChangeType(Object value, Type conversionType, IFormatProvider provider) at System.Xml.Xsl.Runtime.XmlQueryRuntime.ChangeTypeXsltArgument(XmlQueryType xmlType, Object value, Type destinationType) at System.Xml.Xsl.Runtime.XmlQueryContext.InvokeXsltLateBoundFunction(String name, String namespaceUri, IList`1[] args) at (XmlQueryRuntime {urn:schemas-microsoft-com:xslt-debug}runtime) at Root(XmlQueryRuntime {urn:schemas-microsoft-com:xslt-debug}runtime) at System.Xml.Xsl.XmlILCommand.Execute(Object defaultDocument, XmlResolver dataSources, XsltArgumentList argumentList, XmlWriter writer) at System.Xml.Xsl.XslCompiledTransform.Transform(IXPathNavigable input, XsltArgumentList arguments, TextWriter results) at umbraco.presentation.webservices.codeEditorSave.SaveXslt(String fileName, String oldName, String fileContents, Boolean ignoreDebugging)
<!-- Site root --> <xsl:variable name="siteRoot" select="$currentPage/ancestor-or-self::*[@level = 1]" /> <!-- Grab the calendar root --> <xsl:variable name="calendarRoot" select="$siteRoot//EventCalendar"/> <!-- Get any future events --> <xsl:variable name="futureEvents" select="$calendarRoot//Event[not(umbracoNaviHide = 1)][umbraco.library:DateGreaterThanOrEqualToday(eventStartDateTime)]" /> <xsl:value-of select="$siteRoot/@id" disable-output-escaping="yes"/> <!-- just to test the output --> <xsl:choose> <xsl:when test="$futureEvents > 0"> <ul class="events"> <xsl:for-each select="$futureEvents"> ..... </xsl:for-each> </ul> </xsl:when> <xsl:otherwise> <p>Der er i øjeblikket ingen kommende events.</p> </xsl:otherwise> </xsl:choose>
When I test the outputs of the node id's I get: $siteRoot = 1063 which is the top level of my site.. then $calendarRoot = 1133 which also match the id of my Calendar node id... and then $futureEvents = 1138 which is my first event node cause it's placed outside the loop. But somehow it gives me the otherwise value..?
Well then it cause the System.OverflowException: Value was either too large or too small for an Int32. error... I have seen some post that it's should test if the value not is empty or greater than zero.
When I just use the value-of before the choose element it get this as output 2011-08-26T19:00:002011-08-27T00:00:0002 x 18 års fødselsdag Elsted Lystrup beboerhusElsted Skolevej 4, 8520 Lystrup0
Which match the id of $futureEvents = 1138 . So something the variable contains.
Yes - that error usually means that you're calling NiceUrl(), GetMedia() or GetXmlNodeById() with an empty value (or something that's not an Id).
But that has nothing to do with the test for $futureEvents containing something that we just did. You're getting the error because one of the events in the $futureEvents variable has some faulty or missing content - what are you doing inside the loop?
I used this to get check the value of the variables <xsl:value-ofselect="$siteRoot/@id"disable-output-escaping="yes"/>
Is it because the futureEvents variable isn't a node id and therefore the test give an error, like you said: GetXmlNodeById() with an empty value (or something that's not an Id) ..
Yes, the $futureEvents variable is not an Id - it's a node-set that holds <Event> nodes; I'm pretty sure the line that causes the error is the one where you try to link to the EventCalendar at the end - should that link go to the Calendar Root? If so, just use the $calendarRoot variable you created earlier. There is only ONE <EventCalendar> node in the tree, right?
When doing something like this, you should try to split the stuff that's specific for an Event node into its own template - I've refactored your code to do so - try to compare the two versions and decide for yourself which you'd rather like to come back to for edits in a months time or so :-)
<xsl:param name="currentPage"/>
<!-- Site root -->
<xsl:variable name="siteRoot" select="$currentPage/ancestor-or-self::*[@level = 1]" />
<!-- Grab the calendar root -->
<xsl:variable name="calendarRoot" select="$siteRoot//EventCalendar"/>
<!-- Get any future events -->
<xsl:variable name="futureEvents" select="$calendarRoot//Event[not(umbracoNaviHide = 1)][umbraco.library:DateGreaterThanOrEqualToday(eventStartDateTime)]" />
<xsl:variable name="noOfItems" select="2" />
<xsl:template match="/">
<xsl:choose>
<xsl:when test="$futureEvents">
<ul class="events">
<xsl:for-each select="$futureEvents">
<xsl:sort select="eventStartDateTime" order="ascending" />
<xsl:if test="position() <= $noOfItems">
<!-- Process the current Event node -->
<xsl:apply-templates select="." />
</xsl:if>
</xsl:for-each>
</ul>
<!-- Try to comment the following line... -->
<a href="{umbraco.library:NiceUrl($calendarRoot/@id)}" class="small_button"><span>Se kommende events</span></a>
</xsl:when>
<xsl:otherwise>
<p>Der er i øjeblikket ingen kommende events.</p>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<!-- Template for an Event -->
<xsl:template match="Event">
<li>
<div class="event_content">
<div class="news_date">
<!-- No need to test if this is an Event - the template will only run on Event nodes -->
<span class="month"><xsl:value-of select="umbraco.library:FormatDateTime(eventStartDateTime, 'MMM')"/></span>
<span class="day"><xsl:value-of select="umbraco.library:Replace(umbraco.library:FormatDateTime(eventStartDateTime, ' d'), ' ','')"/></span>
<span class="year"><xsl:value-of select="umbraco.library:FormatDateTime(eventStartDateTime, 'yyyy')"/></span>
</div>
<div class="event_desc">
<h2>
<a title="{@nodeName}" href="{umbraco.library:NiceUrl(@id)}">
<!-- Print pageHeading - use @nodeName if pageHeading is empty -->
<xsl:value-of select="(@nodeName[not(normalize-space(../pageHeading))] | pageHeading)[1]" />
</a>
</h2>
<p><a title="{@nodeName}" href="{umbraco.library:NiceUrl(@id)}" class="read_more">Læs mere »</a></p>
</div>
</div>
</li>
</xsl:template>
Yes, I have only one Event Calendar node... and the link just before the otherwise tags in the end should link to the Event Calendar page/node http://ak-security.dk/aktuelt/events.aspx
And you're right.. I have totally overlooked that link... so now I have changed it to use the calendarRoot variable instead... and now it doesn't give me the System.OverflowException: Value was either too large or too small for an Int32. error either, when I remove the greater than zero part from the first when test.
Yes I see what you mean :) I haven't worked much with splitting the content in seperate templates.. only sometimes with paging, but I have got some examples to compare with in these cases.
But yes it gives a much better overview of the content.. I will try to take a deeper look at this.
You can see I get the coming two event on frontpage now: http://ak-security.dk/forside.aspx and the button links to the Event Calendar page..
Thank you so much for taking time to help and your great suggestions... I really appreciate :)
Show only future events
Hi...
I have tried for a while to get the events, but only future events..
I get the events, but it still show events from days before current date.
In content a have the structure Events (alias EventCalendar) > 2011 > August > Event (alias Event) and in my xslt:
<xsl:choose>
<xsl:when test="$currentPage/ancestor-or-self::* [@isDoc]/EventCalendar//* [@isDoc and name()='Event' and umbraco.library:DateGreaterThanOrEqualToday(./eventStartDateTime)] != '0'">
<ul class="events">
<xsl:for-each select="$currentPage/ancestor-or-self::* [@isDoc]/EventCalendar//* [@isDoc and name()='Event' and string(./umbracoNaviHide) != '1']">
....
</ul>
</xsl:when>
<xsl:otherwise>
<p>Der er i øjeblikket ingen kommende events.</p>
</xsl:otherwise>
</xsl:choose>
I would like to use the for-each for all Event nodes and use the test to only show future events..
What am I missing?
Bjarne
put the filter in the for-each:
Hi Daniel
I have tried that and it then it only shows future events, which is what I want.
But if there isn't any events or I have hidden them, then it doesn't show the <p>Der er i øjeblikket ingen kommende events.</p>
Bjarne
It looks like your when condition doesn't check for umbracoNaviHide - I would just copy your xpath from the for-each into your when condition so they are both looking for the same thing.
-Tom
Thanks Tom..
I have the same in the when condition and for-each and seem to work now :)
<xsl:when test="$currentPage/ancestor-or-self::* [@isDoc]/EventCalendar//* [@isDoc and name()='Event' and umbraco.library:DateGreaterThanOrEqualToday(./eventStartDateTime) and string(./umbracoNaviHide) != '1']">
<ul class="events">
<xsl:for-each select="$currentPage/ancestor-or-self::* [@isDoc]/EventCalendar//* [@isDoc and name()='Event' and umbraco.library:DateGreaterThanOrEqualToday(./eventStartDateTime) and string(./umbracoNaviHide) != '1']">
....
</xsl:for-each>
</ul>
</xsl:when>
<xsl:otherwise>
<p>Der er i øjeblikket ingen kommende events.p>
</xsl:otherwise>
</xsl:choose>
Bjarne
Hi Bjarne,
Next time, try to set some variables for yourself - they'll make it easier to see what's going on, e.g.:
Note that I'm checking for umbracoNaviHide first - to save unnecessary calls to the extension function.
/Chriztian
Hi Chriztian
Thanks for your suggestion.
You are right it makes it earsier.. I think it comes with more practice in xslt and I will probably both save time and avoid annoying problems..
Bjarne
I have moved the event calendar down and changed the level to 2, but it doesn't show the coming events on frontpage now?
someone who can see what's wrong?
Bjarne
Hi Bjarne,
Yes - set a variable to the siteRoot, and find the calendarRoot off of that - easier to read/maintain:
/Chriztian
Hi Chriztian
Thanks for your help..
I get a xslt error, withe the code above.
This is what I have now:
<!-- Site root -->
<xsl:variable name="siteRoot" select="$currentPage/ancestor-or-self::*[@level = 2]" />
<!-- Grab the calendar root -->
<xsl:variable name="calendarRoot"select="$siteRoot/*[@nodeName = 'Aktuelt']/EventCalendar"/>
<!-- Get any future events -->
<xsl:variable name="futureEvents" select="$calendarRoot//Event[umbraco.library:DateGreaterThanOrEqualToday(eventStartDateTime) and string(./umbracoNaviHide) != '1']" />
Bjarne
Hi Bjarne,
Ooops - looks like I forgot to change the level for the root - it should be 1:
/Chriztian
Ooh..
Well, it still gives me the xslt error.. hmm..
Okay, it worked before with string(./umbracoNaviHide) != '1'] but it is probably unnessary to calling DateGreaterThanOrEqualToday() function, when the node is hidden..
Bjarne
So what's the error?
(Add ?umbDebugShowTrace=true to the URL and scroll down to the red error description)
/Chriztian
Sorry..
Here it is:
Error loading XSLT eventListHomepage.xslt
XSLT compile error.
at System.Xml.Xsl.Xslt.XsltLoader.LoadStylesheet(XmlReader reader, Boolean include)
at System.Xml.Xsl.Xslt.XsltLoader.Load(Compiler compiler, Object stylesheet, XmlResolver xmlResolver)
at System.Xml.Xsl.Xslt.Compiler.Compile(Object stylesheet, XmlResolver xmlResolver, QilExpression& qil)
at System.Xml.Xsl.XslCompiledTransform.LoadInternal(Object stylesheet, XsltSettings settings, XmlResolver stylesheetResolver)
at umbraco.macro.CreateXsltTransform(XmlTextReader xslReader, Boolean debugMode)
at umbraco.macro.getXslt(String XsltFile)
at umbraco.macro.loadMacroXSLT(macro macro, MacroModel model, Hashtable pageElements)
When I use this line I get the id for the node "Aktuelt":
<xsl:value-of select="$siteRoot/*[@nodeName = 'Aktuelt']/@id" disable-output-escaping="yes"/>
But when I use it in my calendarRoot variable I get this xslt error:
<xsl:variable name="calendarRoot" select="$siteRoot/*[@nodeName = 'Aktuelt']/EventCalendar"/>
Error occured
System.OverflowException: Value was either too large or too small for an Int32.
at System.Convert.ToInt32(Double value)
at System.Convert.ChangeType(Object value, Type conversionType, IFormatProvider provider)
at System.Xml.Xsl.Runtime.XmlQueryRuntime.ChangeTypeXsltArgument(XmlQueryType xmlType, Object value, Type destinationType)
at System.Xml.Xsl.Runtime.XmlQueryContext.InvokeXsltLateBoundFunction(String name, String namespaceUri, IList`1[] args)
at (XmlQueryRuntime {urn:schemas-microsoft-com:xslt-debug}runtime)
at Root(XmlQueryRuntime {urn:schemas-microsoft-com:xslt-debug}runtime)
at System.Xml.Xsl.XmlILCommand.Execute(Object defaultDocument, XmlResolver dataSources, XsltArgumentList argumentList, XmlWriter writer)
at System.Xml.Xsl.XslCompiledTransform.Transform(IXPathNavigable input, XsltArgumentList arguments, TextWriter results)
at umbraco.presentation.webservices.codeEditorSave.SaveXslt(String fileName, String oldName, String fileContents, Boolean ignoreDebugging)
Bjarne
Okay, it doesn't gives me the error when I add a greater than 0.
<!-- Site root -->
<xsl:variable name="siteRoot" select="$currentPage/ancestor-or-self::*[@level = 1]" />
<!-- Grab the calendar root -->
<xsl:variable name="calendarRoot" select="$siteRoot/*[@nodeName = 'Aktuelt']/EventCalendar"/>
<!-- Get any future events -->
<xsl:variable name="futureEvents" select="$calendarRoot//Event[not(umbracoNaviHide = 1)][umbraco.library:DateGreaterThanOrEqualToday(eventStartDateTime)]" />
<xsl:choose>
<xsl:when test="$futureEvents > 0">
<ul class="events">
<xsl:for-each select="$futureEvents">
But it still doesn't give me any nodes as output..
I have hassled with the problem for a while now..
When I test the outputs of the node id's I get: $siteRoot = 1063 which is the top level of my site.. then $calendarRoot = 1133 which also match the id of my Calendar node id... and then $futureEvents = 1138 which is my first event node cause it's placed outside the loop. But somehow it gives me the otherwise value..?
Bjarne
Hi Bjarne,
You shouldn't compare to zero, because $futureEvents is a node-set - just do this:
If the variable contains any nodes, the test will pass.
/Chriztian
Well then it cause the System.OverflowException: Value was either too large or too small for an Int32. error... I have seen some post that it's should test if the value not is empty or greater than zero.
E.g. this post: http://our.umbraco.org/forum/developers/xslt/14608-SystemOverflowException-Value-was-either-too-large-or-too-small-for-an-Int32 or here: http://our.umbraco.org/forum/developers/xslt/22124-Value-was-either-too-large-or-too-small-for-an-Int32-with-GetMedia
When I just use the value-of before the choose element it get this as output
2011-08-26T19:00:002011-08-27T00:00:0002 x 18 års fødselsdag Elsted Lystrup beboerhusElsted Skolevej 4, 8520 Lystrup0
Which match the id of $futureEvents = 1138 . So something the variable contains.
Bjarne
Hi Bjarne,
Yes - that error usually means that you're calling NiceUrl(), GetMedia() or GetXmlNodeById() with an empty value (or something that's not an Id).
But that has nothing to do with the test for $futureEvents containing something that we just did. You're getting the error because one of the events in the $futureEvents variable has some faulty or missing content - what are you doing inside the loop?
/Chriztian
Okay.. my xslt look like this now:
<xsl:param name="currentPage"/>
<xsl:variable name="noOfItems" select="2" />
<xsl:template match="/">
<!-- Site root -->
<xsl:variable name="siteRoot" select="$currentPage/ancestor-or-self::*[@level = 1]" />
<!-- Grab the calendar root -->
<xsl:variable name="calendarRoot" select="$siteRoot//EventCalendar"/>
<!-- Get any future events -->
<xsl:variable name="futureEvents" select="$calendarRoot//Event[not(umbracoNaviHide = 1)][umbraco.library:DateGreaterThanOrEqualToday(eventStartDateTime)]" />
<xsl:choose>
<xsl:when test="$futureEvents > 0">
<ul class="events">
<xsl:for-each select="$futureEvents">
<xsl:sort select="current()/eventStartDateTime" order="ascending" />
<!--<xsl:sort select="@createDate" order="ascending"/>-->
<!-- Position() <= $noOfItems -->
<xsl:if test="position()<= $noOfItems">
<li>
<div class="event_content">
<div class="news_date">
<xsl:choose>
<xsl:when test="name(current()) = 'Event'">
<span class="month"><xsl:value-of select="umbraco.library:FormatDateTime(eventStartDateTime, 'MMM')"/></span>
<span class="day"><xsl:value-of select="umbraco.library:Replace(umbraco.library:FormatDateTime(eventStartDateTime, ' d'), ' ','')"/></span>
<span class="year"><xsl:value-of select="umbraco.library:FormatDateTime(eventStartDateTime, 'yyyy')"/></span>
</xsl:when>
<xsl:otherwise>
<span class="month"><xsl:value-of select="umbraco.library:FormatDateTime(@createDate, 'MMM')"/></span>
<span class="day"><xsl:value-of select="umbraco.library:Replace(umbraco.library:FormatDateTime(@createDate, ' d'), ' ','')"/></span>
<span class="year"><xsl:value-of select="umbraco.library:FormatDateTime(@createDate, 'yyyy')"/></span>
</xsl:otherwise>
</xsl:choose>
</div>
<div class="event_desc">
<h2><a title="{current()/@nodeName}" href="{umbraco.library:NiceUrl(current()/@id)}">
<xsl:choose>
<xsl:when test="./pageHeading != ''">
<xsl:value-of select="current()/pageHeading"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="current()/@nodeName"/>
</xsl:otherwise>
</xsl:choose>
</a>
</h2>
<p><a title="{current()/@nodeName}" href="{umbraco.library:NiceUrl(current()/@id)}" class="read_more">Læs mere »</a></p>
</div>
</div>
</li>
</xsl:if>
</xsl:for-each>
</ul>
<a href="{umbraco.library:NiceUrl($currentPage/ancestor-or-self::* [@isDoc]/EventCalendar/@id)}" class="small_button"><span>Se kommende events</span></a>
</xsl:when>
<xsl:otherwise>
<p>Der er i øjeblikket ingen kommende events.</p>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
But it's the otherwise value I get as output: http://ak-security.dk/forside.aspx
I used this to get check the value of the variables <xsl:value-of select="$siteRoot/@id" disable-output-escaping="yes"/>
Is it because the futureEvents variable isn't a node id and therefore the test give an error, like you said: GetXmlNodeById() with an empty value (or something that's not an Id) ..
Bjarne
Hi Bjarne,
Yes, the $futureEvents variable is not an Id - it's a node-set that holds <Event> nodes; I'm pretty sure the line that causes the error is the one where you try to link to the EventCalendar at the end - should that link go to the Calendar Root? If so, just use the $calendarRoot variable you created earlier. There is only ONE <EventCalendar> node in the tree, right?
When doing something like this, you should try to split the stuff that's specific for an Event node into its own template - I've refactored your code to do so - try to compare the two versions and decide for yourself which you'd rather like to come back to for edits in a months time or so :-)
/Chriztian
Hi Chriztian
Yes, I have only one Event Calendar node... and the link just before the otherwise tags in the end should link to the Event Calendar page/node http://ak-security.dk/aktuelt/events.aspx
And you're right.. I have totally overlooked that link... so now I have changed it to use the calendarRoot variable instead... and now it doesn't give me the System.OverflowException: Value was either too large or too small for an Int32. error either, when I remove the greater than zero part from the first when test.
Yes I see what you mean :) I haven't worked much with splitting the content in seperate templates.. only sometimes with paging, but I have got some examples to compare with in these cases.
But yes it gives a much better overview of the content.. I will try to take a deeper look at this.
You can see I get the coming two event on frontpage now: http://ak-security.dk/forside.aspx and the button links to the Event Calendar page..
Thank you so much for taking time to help and your great suggestions... I really appreciate :)
Bjarne
is working on a reply...