The idea is that if the node has this property and it's populated with something then it would appear in the A-Z list. I thought I could use a .distinct() to get the first letter of the property and then list each node that starts with that initial.
From the XSLT extension I wanted to return an XML navigator that looked something like
where the initial element was only there if there were matches for the documents.
I can do the last bit to generate the XML but I am really not sure what the best approach to getting the unique initial letters is and then joining that to the list of nodes (the name attribute is really very optional above and onlu really to illustrate what is going on, though I can see it could be nice).
namespace bucksCC.extensions.XSLTExtension { [XsltExtension(Namespace = "sa.umb.atoz")] public class AtoZ { public static string initials() { IEnumerable<nodeAZ> azNodes = uQuery.GetRootNode().GetDescendantOrSelfNodes() .Where(w => w.GetProperty<string>("navAZ") != "") .Select( n => new nodeAZ(n.Id.ToString(),n.GetProperty<string>("navAZ"))); IEnumerable<char> initials = azNodes .Select(c => c.Initial).Distinct().OrderBy(c => c); var joined = initials .GroupJoin(azNodes, i => i, n => n.Initial, (i, n) => new { letters = i, nodes = n }); XDocument xdoc = new XDocument(new XElement("AtoZ", from l in joined select new XElement("Initial", new XAttribute("letter", l.letters), new XElement("Nodes", from Elements in l.nodes select new XElement("Node", new XAttribute("ID", Elements.ID), new XAttribute("Name", Elements.Name) ) ) ))); return xdoc.ToString(); } } public class nodeAZ { public string ID { get; set; } public string Name { get; set; } public char Initial { get; set; } public nodeAZ(string id, string name) { ID = id; Name = name; Initial = name[0]; } } }
...will change return type to node iterator and not return just the xml string and also make the paramater passed in the doctype property rather than hard coding this
I really can't tell if this is the rantings of a mad man or really ok - i'd appreciate any criticism :)
things that would be nice to know would be how to do the last bit as lambda if that makes any sense and also how not to have the nodes wrapping the node elements
and generally how maybe this could be clearer and simpler
Take a look at the Enumerable.GroupBy() method. You could do something like this:
// get the nodes
var nodes = uQuery.GetNodesByXPath("//*[@isDoc]");
// group the nodes by first letter
var grouping = nodes.GroupBy<umbraco.NodeFactory.Node, char>(x => char.ToUpper(x.Name[0]));
// loop the grouping
foreach (var item in grouping)
{
// item.Key - contains the letter
foreach (var node in item)
{
// node.Name
}
}
linq to get unique A-Z list
I was trying to make an XSLT extension that can use linq to build an A-Z list page.
I added a document property called "navAZ"
As far as I got so far was:
where the initial element was only there if there were matches for the documents.
I can do the last bit to generate the XML but I am really not sure what the best approach to getting the unique initial letters is and then joining that to the list of nodes (the name attribute is really very optional above and onlu really to illustrate what is going on, though I can see it could be nice).
Well this is where I got to:
...will change return type to node iterator and not return just the xml string and also make the paramater passed in the doctype property rather than hard coding this
I really can't tell if this is the rantings of a mad man or really ok - i'd appreciate any criticism :)
things that would be nice to know would be
how to do the last bit as lambda if that makes any sense
and also how not to have the nodes wrapping the node elements
and generally how maybe this could be clearer and simpler
the xml i get out looks like this
Hi John,
Take a look at the Enumerable.GroupBy() method. You could do something like this:
Cheers, Lee.
is working on a reply...