These templates should do it - I'm a little baffled about not having $currentPage, but maybe you can shed some light on the context you're doing this in...
Thanks for coming back, my bad... I didn't explain properly... I am actually going to use this in a .NET usercontrol, and I am going to use Hendys helper class which has a method in it called GetNodesFromXpath()
Because of this I don't have XSLT available to me, just an XPath statement which will return me a set of Node object(s). the reason currentPage won't help is because this marco which loops through the main forum categories could be put anywhere on the site and at any level, so currentPage won't help will it? Although looking at the below I notice currentPage is used in the method
Here is the GetNodesFromXpath() method which I need to pass the XPath query into
public static List<Node> GetNodesFromXpath(string xPath)
{
var nodes = new List<Node>();
if (IsCurrentNodeAvailable())
{
xPath = xPath.Replace("$currentPage", "descendant::node[@id='" + Node.GetCurrent().Id + "']");
}
var xPathNavigator = umbraco.content.Instance.XmlContent.CreateNavigator(); //get all umbraco xml
var xPathNodeIterator = xPathNavigator.Select(xPath); //TODO: check xpath string is valid
Node node;
while (xPathNodeIterator.MoveNext())
{
node = GetNode(xPathNodeIterator.Current.Evaluate("string(@id)").ToString());
if (node != null) { nodes.Add(node); }
}
return nodes;
}
It will take more than a single xpath to do everything you want so I think you've got a non-starter here, Lee.
But, for what it's worth, you might be able to make some assumptions about where the forum is located and save a variable for the top forum node (so you don't have to do the inefficient work of descendant-or-self more than once):
<!-- If it will be at the top of the content tree as its own site --> <xsl:variable name="forumHome" select="$currentPage/ancestor-or-self::root/Forum" />
<!-- if it will be directly below the homepage of the site currently being viewed --> <xsl:variable name="forumHome" select="$currentPage/ancestor-or-self::*[@level = 1]/Forum" />
<!-- if it will be within the site the website visitor is currently viewing (can be very slow on big sites) --> <xsl:variable name="forumHome" select="$currentPage/ancestor-or-self::*[@level = 1]/descendant-or-self::Forum" />
<!-- if it can be anywhere (can be extremely slow on big sites) --> <xsl:variable name="forumHome" select="$currentPage/ancesotor-or-self::root/descendant-or-self::Forum" />
But probably better would be to have a macro parameter with a ContentPicker that asks the user to select the Forum's home page. Then you know the id and don't have to do any slow searching/guessing to find it.
You can, of course, use .net to do this work but since it is all xpath based anyway I don't see an advantage - more a matter of preference. The big point is simply that this isn't a one-liner no matter the language.
The reason I need to do this in .NET is because its in a partial class..
@Doug - I have the Root forum Node Id available to me which I can pass into the query if needed? Would that help create an efficient XPath query? I am trying to use this instead of Linq2umbraco as its very slow, so trying to use a mix of the good and bad to increase performance on big sites.
Thought: Since the problem involves 2 steps (sorting by date descending and then picking the top-most) the first of which you can't do in XPath, maybe you could create an extension max() function - the dates are sortable strings so should probably be doable without the overhead of casting to Dates etc.
Thanks everyone for posting about this... I have decided to go about it a different way at the moment but may revert back to this. Its a bit of a cheat, but I am trying to make sure everything will work with a 100K+ node site with good performance.
XPath Query Help
Ok so I have the following structure
Forum
- ForumCategory
- ForumTopic
- ForumPost
- ForumPost
- ForumPost
- ForumTopic
- ForumPost
- ForumPost
- ForumPost
- ForumTopic
- ForumPost
- ForumPost
- ForumPost
- ForumCategory
- ForumTopic
- ForumPost
- ForumPost
- ForumPost
- ForumTopic
- ForumPost
- ForumPost
- ForumPost
- ForumTopic
- ForumPost
- ForumPost
- ForumPost
When I list out the categories I want to find the latest post in that category, so I need to find it by createDate.. i.e...
Category Name Latest Post '18/02/78'
Category Name Latest Post '18/02/78'
Category Name Latest Post '18/02/78'
When looping through I have each Category nodeID available to me only, currentPage is not as its a standalone macro which people can add anywhere.
Any help greatly appreciated...
Hi Lee,
These templates should do it - I'm a little baffled about not having $currentPage, but maybe you can shed some light on the context you're doing this in...
/Chriztian
Hey Chriztian
Thanks for coming back, my bad... I didn't explain properly... I am actually going to use this in a .NET usercontrol, and I am going to use Hendys helper class which has a method in it called GetNodesFromXpath()
Because of this I don't have XSLT available to me, just an XPath statement which will return me a set of Node object(s). the reason currentPage won't help is because this marco which loops through the main forum categories could be put anywhere on the site and at any level, so currentPage won't help will it? Although looking at the below I notice currentPage is used in the method
Here is the GetNodesFromXpath() method which I need to pass the XPath query into
and the reason you need a .NET usercontrol?
Chriztian's solution seems valid to me (and can be put everywhere aswell).
It will take more than a single xpath to do everything you want so I think you've got a non-starter here, Lee.
But, for what it's worth, you might be able to make some assumptions about where the forum is located and save a variable for the top forum node (so you don't have to do the inefficient work of descendant-or-self more than once):
But probably better would be to have a macro parameter with a ContentPicker that asks the user to select the Forum's home page. Then you know the id and don't have to do any slow searching/guessing to find it.
You can, of course, use .net to do this work but since it is all xpath based anyway I don't see an advantage - more a matter of preference. The big point is simply that this isn't a one-liner no matter the language.
cheers,
doug.
The reason I need to do this in .NET is because its in a partial class..
@Doug - I have the Root forum Node Id available to me which I can pass into the query if needed? Would that help create an efficient XPath query? I am trying to use this instead of Linq2umbraco as its very slow, so trying to use a mix of the good and bad to increase performance on big sites.
Ah, if you've got the forumHome then you can create an xpathnodeiterator and do the logic Chriztian notes in .net. Performance ought to be okay.
cheers,
doug.
Of course I say that not having done this myself. For memory savings, only get the forum nodes for your xPathNavigator.
Let us know what you come up with and how the performance goes.
cheers,
doug.
Thought: Since the problem involves 2 steps (sorting by date descending and then picking the top-most) the first of which you can't do in XPath, maybe you could create an extension max() function - the dates are sortable strings so should probably be doable without the overhead of casting to Dates etc.
That way you could say something like this:
But then again, I wouldn't trust my .NET skills that much :-)
/Chriztian
Lee.Mess
That works on sooooo many levels! :D
Thanks everyone for posting about this... I have decided to go about it a different way at the moment but may revert back to this. Its a bit of a cheat, but I am trying to make sure everything will work with a 100K+ node site with good performance.
is working on a reply...