Files
Umbraco-CMS/umbraco.MacroEngines.Juno/RazorDynamicNode/DynamicXml.cs
agrath@gmail.com 0ea4e2f891 Added IsHelpers to DynamicXml
Added As<T>() [ return (item as T); ] to @Library
Added ToDynamicXml(string) to @Library
2011-06-12 11:50:35 -02:00

527 lines
20 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Dynamic;
using System.Xml.Linq;
using System.Xml.XPath;
using System.Collections;
namespace umbraco.MacroEngines
{
public class DynamicXml : DynamicObject, IEnumerable
{
public XElement BaseElement { get; set; }
public DynamicXml(XElement baseElement)
{
this.BaseElement = baseElement;
}
public string InnerText
{
get
{
return BaseElement.Value;
}
}
public override bool TryGetIndex(GetIndexBinder binder, object[] indexes, out object result)
{
int index = 0;
if (indexes.Length > 0)
{
index = (int)indexes[0];
result = new DynamicXml(this.BaseElement.Elements().ToList()[index]);
return true;
}
return base.TryGetIndex(binder, indexes, out result);
}
public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result)
{
if (args.Length == 0 && binder.Name == "ToXml")
{
result = this.BaseElement.ToString();
return true;
}
if (args.Length == 1 && binder.Name == "XPath")
{
var elements = this.BaseElement.XPathSelectElements(args[0].ToString());
HandleIEnumerableXElement(elements, out result);
return true; //anyway
}
return base.TryInvokeMember(binder, args, out result);
}
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
//Go ahead and try to fetch all of the elements matching the member name, and wrap them
var elements = BaseElement.Elements(binder.Name);
if (HandleIEnumerableXElement(elements, out result))
{
return true;
}
else
{
//Ok, so no elements matched, so lets try attributes
var attributes = BaseElement.Attributes(binder.Name).Select(attr => attr.Value);
int count = attributes.Count();
if (count > 0)
{
if (count > 1)
result = attributes; //more than one attribute matched, lets return the collection
else
result = attributes.FirstOrDefault(); //only one attribute matched, lets just return it
return true; // return true because we matched
}
}
return base.TryGetMember(binder, out result);
}
private bool HandleIEnumerableXElement(IEnumerable<XElement> elements, out object result)
{
//Get the count now, so we don't have to call it twice
int count = elements.Count();
if (count > 0)
{
var firstElement = elements.FirstOrDefault();
//we have a single element, does it have any children?
if (firstElement != null && firstElement.Elements().Count() == 0 && !firstElement.HasAttributes)
{
//no, return the text
result = firstElement.Value;
return true;
}
else
{
//We have more than one matching element, so let's return the collection
//elements is IEnumerable<DynamicXml>
//but we want to be able to re-enter this code
XElement root = new XElement(XName.Get("root"));
root.Add(elements);
result = new DynamicXml(root);
//From here, you'll either end up back here (because you have <root><node><node>)
//or you use [] indexing and you end up with a single element
return true;
}
}
result = null;
return false;
}
public IEnumerator GetEnumerator()
{
return this.BaseElement.Elements().Select(e => new DynamicXml(e)).GetEnumerator();
}
public int Count()
{
return this.BaseElement.Elements().Count();
}
public bool IsNull()
{
return false;
}
public bool HasValue()
{
return true;
}
public bool IsFirst()
{
return IsHelper(n => n.Index() == 0);
}
public string IsFirst(string valueIfTrue)
{
return IsHelper(n => n.Index() == 0, valueIfTrue);
}
public string IsFirst(string valueIfTrue, string valueIfFalse)
{
return IsHelper(n => n.Index() == 0, valueIfTrue, valueIfFalse);
}
public bool IsNotFirst()
{
return !IsHelper(n => n.Index() == 0);
}
public string IsNotFirst(string valueIfTrue)
{
return IsHelper(n => n.Index() != 0, valueIfTrue);
}
public string IsNotFirst(string valueIfTrue, string valueIfFalse)
{
return IsHelper(n => n.Index() != 0, valueIfTrue, valueIfFalse);
}
public bool IsPosition(int index)
{
if (this.BaseElement == null || this.BaseElement.Parent == null)
{
return false;
}
return IsHelper(n => n.Index() == index);
}
public string IsPosition(int index, string valueIfTrue)
{
if (this.BaseElement == null || this.BaseElement.Parent == null)
{
return string.Empty;
}
return IsHelper(n => n.Index() == index, valueIfTrue);
}
public string IsPosition(int index, string valueIfTrue, string valueIfFalse)
{
if (this.BaseElement == null || this.BaseElement.Parent == null)
{
return valueIfFalse;
}
return IsHelper(n => n.Index() == index, valueIfTrue, valueIfFalse);
}
public bool IsModZero(int modulus)
{
if (this.BaseElement == null || this.BaseElement.Parent == null)
{
return false;
}
return IsHelper(n => n.Index() % modulus == 0);
}
public string IsModZero(int modulus, string valueIfTrue)
{
if (this.BaseElement == null || this.BaseElement.Parent == null)
{
return string.Empty;
}
return IsHelper(n => n.Index() % modulus == 0, valueIfTrue);
}
public string IsModZero(int modulus, string valueIfTrue, string valueIfFalse)
{
if (this.BaseElement == null || this.BaseElement.Parent == null)
{
return valueIfFalse;
}
return IsHelper(n => n.Index() % modulus == 0, valueIfTrue, valueIfFalse);
}
public bool IsNotModZero(int modulus)
{
if (this.BaseElement == null || this.BaseElement.Parent == null)
{
return false;
}
return IsHelper(n => n.Index() % modulus != 0);
}
public string IsNotModZero(int modulus, string valueIfTrue)
{
if (this.BaseElement == null || this.BaseElement.Parent == null)
{
return string.Empty;
}
return IsHelper(n => n.Index() % modulus != 0, valueIfTrue);
}
public string IsNotModZero(int modulus, string valueIfTrue, string valueIfFalse)
{
if (this.BaseElement == null || this.BaseElement.Parent == null)
{
return valueIfFalse;
}
return IsHelper(n => n.Index() % modulus != 0, valueIfTrue, valueIfFalse);
}
public bool IsNotPosition(int index)
{
if (this.BaseElement == null || this.BaseElement.Parent == null)
{
return false;
}
return !IsHelper(n => n.Index() == index);
}
public string IsNotPosition(int index, string valueIfTrue)
{
if (this.BaseElement == null || this.BaseElement.Parent == null)
{
return string.Empty;
}
return IsHelper(n => n.Index() != index, valueIfTrue);
}
public string IsNotPosition(int index, string valueIfTrue, string valueIfFalse)
{
if (this.BaseElement == null || this.BaseElement.Parent == null)
{
return valueIfFalse;
}
return IsHelper(n => n.Index() != index, valueIfTrue, valueIfFalse);
}
public bool IsLast()
{
if (this.BaseElement == null || this.BaseElement.Parent == null)
{
return false;
}
int count = this.BaseElement.Parent.Elements().Count();
return IsHelper(n => n.Index() == count - 1);
}
public string IsLast(string valueIfTrue)
{
if (this.BaseElement == null || this.BaseElement.Parent == null)
{
return string.Empty;
}
int count = this.BaseElement.Parent.Elements().Count();
return IsHelper(n => n.Index() == count - 1, valueIfTrue);
}
public string IsLast(string valueIfTrue, string valueIfFalse)
{
if (this.BaseElement == null || this.BaseElement.Parent == null)
{
return valueIfFalse;
}
int count = this.BaseElement.Parent.Elements().Count();
return IsHelper(n => n.Index() == count - 1, valueIfTrue, valueIfFalse);
}
public bool IsNotLast()
{
if (this.BaseElement == null || this.BaseElement.Parent == null)
{
return false;
}
int count = this.BaseElement.Parent.Elements().Count();
return !IsHelper(n => n.Index() == count - 1);
}
public string IsNotLast(string valueIfTrue)
{
if (this.BaseElement == null || this.BaseElement.Parent == null)
{
return string.Empty;
}
int count = this.BaseElement.Parent.Elements().Count();
return IsHelper(n => n.Index() != count - 1, valueIfTrue);
}
public string IsNotLast(string valueIfTrue, string valueIfFalse)
{
if (this.BaseElement == null || this.BaseElement.Parent == null)
{
return valueIfFalse;
}
int count = this.BaseElement.Parent.Elements().Count();
return IsHelper(n => n.Index() != count - 1, valueIfTrue, valueIfFalse);
}
public bool IsEven()
{
return IsHelper(n => n.Index() % 2 == 0);
}
public string IsEven(string valueIfTrue)
{
return IsHelper(n => n.Index() % 2 == 0, valueIfTrue);
}
public string IsEven(string valueIfTrue, string valueIfFalse)
{
return IsHelper(n => n.Index() % 2 == 0, valueIfTrue, valueIfFalse);
}
public bool IsOdd()
{
return IsHelper(n => n.Index() % 2 == 1);
}
public string IsOdd(string valueIfTrue)
{
return IsHelper(n => n.Index() % 2 == 1, valueIfTrue);
}
public string IsOdd(string valueIfTrue, string valueIfFalse)
{
return IsHelper(n => n.Index() % 2 == 1, valueIfTrue, valueIfFalse);
}
public bool IsEqual(DynamicXml other)
{
return IsHelper(n => n.BaseElement == other.BaseElement);
}
public string IsEqual(DynamicXml other, string valueIfTrue)
{
return IsHelper(n => n.BaseElement == other.BaseElement, valueIfTrue);
}
public string IsEqual(DynamicXml other, string valueIfTrue, string valueIfFalse)
{
return IsHelper(n => n.BaseElement == other.BaseElement, valueIfTrue, valueIfFalse);
}
public bool IsDescendant(DynamicXml other)
{
var ancestors = this.Ancestors();
return IsHelper(n => ancestors.Find(ancestor => ancestor.BaseElement == other.BaseElement) != null);
}
public string IsDescendant(DynamicXml other, string valueIfTrue)
{
var ancestors = this.Ancestors();
return IsHelper(n => ancestors.Find(ancestor => ancestor.BaseElement == other.BaseElement) != null, valueIfTrue);
}
public string IsDescendant(DynamicXml other, string valueIfTrue, string valueIfFalse)
{
var ancestors = this.Ancestors();
return IsHelper(n => ancestors.Find(ancestor => ancestor.BaseElement == other.BaseElement) != null, valueIfTrue, valueIfFalse);
}
public bool IsDescendantOrSelf(DynamicXml other)
{
var ancestors = this.AncestorsOrSelf();
return IsHelper(n => ancestors.Find(ancestor => ancestor.BaseElement == other.BaseElement) != null);
}
public string IsDescendantOrSelf(DynamicXml other, string valueIfTrue)
{
var ancestors = this.AncestorsOrSelf();
return IsHelper(n => ancestors.Find(ancestor => ancestor.BaseElement == other.BaseElement) != null, valueIfTrue);
}
public string IsDescendantOrSelf(DynamicXml other, string valueIfTrue, string valueIfFalse)
{
var ancestors = this.AncestorsOrSelf();
return IsHelper(n => ancestors.Find(ancestor => ancestor.BaseElement == other.BaseElement) != null, valueIfTrue, valueIfFalse);
}
public bool IsAncestor(DynamicXml other)
{
var descendants = this.Descendants();
return IsHelper(n => descendants.Find(descendant => descendant.BaseElement == other.BaseElement) != null);
}
public string IsAncestor(DynamicXml other, string valueIfTrue)
{
var descendants = this.Descendants();
return IsHelper(n => descendants.Find(descendant => descendant.BaseElement == other.BaseElement) != null, valueIfTrue);
}
public string IsAncestor(DynamicXml other, string valueIfTrue, string valueIfFalse)
{
var descendants = this.Descendants();
return IsHelper(n => descendants.Find(descendant => descendant.BaseElement == other.BaseElement) != null, valueIfTrue, valueIfFalse);
}
public bool IsAncestorOrSelf(DynamicXml other)
{
var descendants = this.DescendantsOrSelf();
return IsHelper(n => descendants.Find(descendant => descendant.BaseElement == other.BaseElement) != null);
}
public string IsAncestorOrSelf(DynamicXml other, string valueIfTrue)
{
var descendants = this.DescendantsOrSelf();
return IsHelper(n => descendants.Find(descendant => descendant.BaseElement == other.BaseElement) != null, valueIfTrue);
}
public string IsAncestorOrSelf(DynamicXml other, string valueIfTrue, string valueIfFalse)
{
var descendants = this.DescendantsOrSelf();
return IsHelper(n => descendants.Find(descendant => descendant.BaseElement == other.BaseElement) != null, valueIfTrue, valueIfFalse);
}
public List<DynamicXml> Descendants()
{
return Descendants(n => true);
}
public List<DynamicXml> Descendants(Func<XElement, bool> func)
{
var flattenedNodes = this.BaseElement.Elements().Map(func, (XElement n) => { return n.Elements(); });
return flattenedNodes.ToList().ConvertAll(n => new DynamicXml(n));
}
public List<DynamicXml> DescendantsOrSelf()
{
return DescendantsOrSelf(n => true);
}
public List<DynamicXml> DescendantsOrSelf(Func<XElement, bool> func)
{
var flattenedNodes = this.BaseElement.Elements().Map(func, (XElement n) => { return n.Elements(); });
var list = new List<DynamicXml>();
list.Add(this);
list.AddRange(flattenedNodes.ToList().ConvertAll(n => new DynamicXml(n)));
return list;
}
public List<DynamicXml> Ancestors()
{
return Ancestors(item => true);
}
public List<DynamicXml> Ancestors(Func<XElement, bool> func)
{
List<XElement> ancestorList = new List<XElement>();
var node = this.BaseElement;
while (node != null)
{
if (node.Parent == null) break;
XElement parent = node.Parent;
if (parent != null)
{
if (this.BaseElement != parent)
{
node = parent;
if (func(node))
{
ancestorList.Add(node);
}
}
else
{
break;
}
}
else
{
break;
}
}
ancestorList.Reverse();
return ancestorList.ConvertAll(item => new DynamicXml(item));
}
public List<DynamicXml> AncestorsOrSelf()
{
return AncestorsOrSelf(item => true);
}
public List<DynamicXml> AncestorsOrSelf(Func<XElement, bool> func)
{
List<XElement> ancestorList = new List<XElement>();
var node = this.BaseElement;
ancestorList.Add(node);
while (node != null)
{
if (node.Parent == null) break;
XElement parent = node.Parent;
if (parent != null)
{
if (this.BaseElement != parent)
{
node = parent;
if (func(node))
{
ancestorList.Add(node);
}
}
else
{
break;
}
}
else
{
break;
}
}
ancestorList.Reverse();
return ancestorList.ConvertAll(item => new DynamicXml(item));
}
public int Index()
{
if (this.BaseElement != null && this.BaseElement.Parent != null)
{
var elements = this.BaseElement.Parent.Elements();
int index = 0;
foreach (var element in elements)
{
if (element == this.BaseElement) break;
index++;
}
return index;
}
return 0;
}
public bool IsHelper(Func<DynamicXml, bool> test)
{
return test(this);
}
public string IsHelper(Func<DynamicXml, bool> test, string valueIfTrue)
{
return IsHelper(test, valueIfTrue, string.Empty);
}
public string IsHelper(Func<DynamicXml, bool> test, string valueIfTrue, string valueIfFalse)
{
return test(this) ? valueIfTrue : valueIfFalse;
}
}
}