From 84d7999f3283453d7858f827bb2265fb3ffa25cd Mon Sep 17 00:00:00 2001 From: "agrath@gmail.com" Date: Sat, 19 Feb 2011 20:05:02 -1300 Subject: [PATCH] Added .XPath helper to DynamicNode list that allows you to use XPath to query from the current node represented in XML (e.g. if you have a child DynamicNode which actually exists part way down the original dom from NodeFactory then get it at that position (allowing you to use .. to move to parent) Nodes are attempted to be turned back into NodeFactory.Node when returned by XPath and then wrapped in DynamicNode and then DynamicNodeList Added .Random parameterless overload to pick a single random node from the DynamicNodeList Example of new Methods being used: --- umbraco.MacroEngines.Juno/DynamicNode.cs | 61 +++++++++++++++++++ .../DynamicNodeListExtensionMethods.cs | 5 ++ 2 files changed, 66 insertions(+) diff --git a/umbraco.MacroEngines.Juno/DynamicNode.cs b/umbraco.MacroEngines.Juno/DynamicNode.cs index bd62ddbdf2..a255d7ef05 100644 --- a/umbraco.MacroEngines.Juno/DynamicNode.cs +++ b/umbraco.MacroEngines.Juno/DynamicNode.cs @@ -11,6 +11,7 @@ using umbraco.cms.businesslogic.property; using umbraco.BusinessLogic; using umbraco.DataLayer; using umbraco.cms.businesslogic; +using System.Xml; namespace umbraco.MacroEngines @@ -63,6 +64,66 @@ namespace umbraco.MacroEngines return new DynamicNodeList(n.ChildrenAsList); } } + public DynamicNodeList XPath(string xPath) + { + //if this DN was initialized with an underlying NodeFactory.Node + if (n != null) + { + //get the underlying xml content + XmlDocument doc = umbraco.content.Instance.XmlContent; + if (doc != null) + { + //get n as a XmlNode (to be used as the context point for the xpath) + //rather than just applying the xPath to the root node, this lets us use .. etc from the DynamicNode point + + + //in test mode, n.Id is 0, let this always succeed + if (n.Id == 0) + { + List emptyList = new List(); + return new DynamicNodeList(emptyList); + } + XmlNode node = doc.SelectSingleNode(string.Format("//*[@id='{0}']", n.Id)); + if (node != null) + { + //got the current node (within the XmlContent instance) + XmlNodeList nodes = node.SelectNodes(xPath); + if (nodes.Count > 0) + { + //we got some resulting nodes + List nodeFactoryNodeList = new List(); + //attempt to convert each node in the set to a NodeFactory.Node + foreach (XmlNode nodeXmlNode in nodes) + { + try + { + nodeFactoryNodeList.Add(new NodeFactory.Node(nodeXmlNode)); + } + catch (Exception) { } //swallow the exceptions - the returned nodes might not be full nodes, e.g. property + } + //convert the NodeFactory nodelist to IEnumerable and return it as a DynamicNodeList + return new DynamicNodeList(nodeFactoryNodeList.ConvertAll(nfNode => new DynamicNode(nfNode))); + } + else + { + throw new NullReferenceException("XPath returned no nodes"); + } + } + else + { + throw new NullReferenceException("Couldn't locate the DynamicNode within the XmlContent"); + } + } + else + { + throw new NullReferenceException("umbraco.content.Instance.XmlContent is null"); + } + } + else + { + throw new NullReferenceException("DynamicNode wasn't initialized with an underlying NodeFactory.Node"); + } + } public override bool TryGetMember(GetMemberBinder binder, out object result) { diff --git a/umbraco.MacroEngines.Juno/DynamicNodeListExtensionMethods.cs b/umbraco.MacroEngines.Juno/DynamicNodeListExtensionMethods.cs index 8740553a06..f25427b83c 100644 --- a/umbraco.MacroEngines.Juno/DynamicNodeListExtensionMethods.cs +++ b/umbraco.MacroEngines.Juno/DynamicNodeListExtensionMethods.cs @@ -21,5 +21,10 @@ namespace umbraco.MacroEngines //Randomly order the items in the set by a Guid, Take the correct number, and return this wrapped in a new DynamicNodeList return new DynamicNodeList(all.Items.OrderBy(x => Guid.NewGuid()).Take(Max)); } + + public static DynamicNode Random(this DynamicNodeList all) + { + return all.Items.OrderBy(x => Guid.NewGuid()).First(); + } } } \ No newline at end of file