<PackageReference Include="Castle.Core" Version="3.0.0.2001" />

XPathResult

public class XPathResult
using System; using System.Collections.Generic; using System.Linq; using System.Xml.Serialization; using System.Xml.XPath; namespace Castle.Components.DictionaryAdapter { public class XPathResult { public readonly bool CanWrite; private readonly object matchingBehavior; private readonly Func<XPathNavigator> create; private static readonly Dictionary<Type, string> XmlDataTypes = new Dictionary<Type, string> { { typeof(int), "int" }, { typeof(long), "long" }, { typeof(short), "short" }, { typeof(float), "float" }, { typeof(double), "double" }, { typeof(bool), "boolean" }, { typeof(DateTime), "dateTime" }, { typeof(byte), "byte" }, { typeof(uint), "uint" }, { typeof(ulong), "ulong" }, { typeof(ushort), "ushort" } }; public bool IsContainer { get { if (matchingBehavior != null) return matchingBehavior is XmlArrayAttribute; return true; } } public Type Type { get; set; } public PropertyDescriptor Property { get; set; } public string Key { get; set; } public object Result { get; set; } public XPathContext Context { get; set; } public XPathNavigator Container { get; set; } public XmlMetadata XmlMeta { get; set; } public bool OmitPolymorphism { get; set; } public bool IsNullable { get { if (Result is XPathNavigator && ((XPathNavigator)Result).NodeType != XPathNodeType.Element) return false; if (matchingBehavior == null) return Context.IsNullable; if (matchingBehavior is XmlElementAttribute) return ((XmlElementAttribute)matchingBehavior).IsNullable; if (matchingBehavior is XmlArrayAttribute) return ((XmlArrayAttribute)matchingBehavior).IsNullable; if (matchingBehavior is XmlArrayItemAttribute) return ((XmlArrayItemAttribute)matchingBehavior).IsNullable; return Context.IsNullable; } } public XPathResult(PropertyDescriptor property, string key, object result, XPathContext context, object matchingBehavior) : this(property, key, result, context, matchingBehavior, null) { } public XPathResult(Type type, object result, XPathContext context, object matchingBehavior) : this(null, null, result, context, matchingBehavior, null) { Type = type; } public XPathResult(PropertyDescriptor property, string key, object result, XPathContext context, object matchingBehavior, Func<XPathNavigator> create) { Result = result; Property = property; Key = key; Type = ((property != null) ? Property.PropertyType : null); Context = context; this.create = create; this.matchingBehavior = matchingBehavior; CanWrite = (create != null || result is XPathNavigator); } public XPathNavigator GetNavigator(bool demand) { GetNavigator(demand, false, out XPathNavigator result); return result; } public bool GetNavigator(bool demand, bool nillable, out XPathNavigator result) { if (Result is XPathNavigator) { result = (XPathNavigator)Result; if (!nillable) return true; return GetNillable(ref result); } if (Result is XPathNodeIterator) { result = ((XPathNodeIterator)Result).Cast<XPathNavigator>().FirstOrDefault(); if (!nillable) return true; return GetNillable(ref result); } if (demand && create != null) { result = create(); Result = result; return true; } result = null; return true; } public XPathResult GetNodeAt(Type type, int index) { XPathNavigator xPathNavigator = Container; if (IsContainer) { if (xPathNavigator != null) xPathNavigator = Container.SelectSingleNode($"""{index + 1}"""); } else if (Result is XPathNodeIterator) { XPathNavigator[] array = ((XPathNodeIterator)Result).Cast<XPathNavigator>().ToArray(); xPathNavigator = array[index]; } return new XPathResult(type, xPathNavigator, Context, Context.ListItemMeta ?? matchingBehavior); } public IEnumerable<XPathResult> GetNodes(Type type, Func<Type, XmlMetadata> getXmlMeta) { Container = null; XPathNodeIterator xPathNodeIterator = Result as XPathNodeIterator; IEnumerable<XPathNavigator> source = Enumerable.Empty<XPathNavigator>(); if (xPathNodeIterator == null) { Container = (Result as XPathNavigator); if (IsContainer && Container != null) { if (Context.IsNil(Container)) return null; if (Context.ListItemMeta != null) return Context.ListItemMeta.SelectMany(delegate(XmlArrayItemAttribute item) { string name2; string namespaceUri2; XmlMetadata xmlMeta2 = GetItemQualifedName(type, item, getXmlMeta, out name2, out namespaceUri2); return from XPathNavigator r in Container.SelectChildren(name2, namespaceUri2) select new XPathResult(item.Type ?? type, r, Context, item) { XmlMeta = xmlMeta2 }; }).OrderBy((XPathResult r) => (XPathNavigator)r.Result, XPathPositionComparer.Instance); source = Container.SelectChildren(XPathNodeType.Element).Cast<XPathNavigator>(); } } else if (!IsContainer) { source = xPathNodeIterator.Cast<XPathNavigator>(); } else { List<XPathNavigator> parents = xPathNodeIterator.Cast<XPathNavigator>().ToList(); Container = parents.FirstOrDefault(); if (Context.IsNil(Container)) return null; if (Context.ListItemMeta != null) return Context.ListItemMeta.SelectMany(delegate(XmlArrayItemAttribute item) { string name; string namespaceUri; XmlMetadata xmlMeta = GetItemQualifedName(type, item, getXmlMeta, out name, out namespaceUri); return from r in parents.SelectMany((XPathNavigator p) => p.SelectChildren(name, namespaceUri).Cast<XPathNavigator>()) select new XPathResult(item.Type ?? type, r, Context, item) { XmlMeta = xmlMeta }; }).OrderBy((XPathResult r) => (XPathNavigator)r.Result, XPathPositionComparer.Instance); source = parents.SelectMany((XPathNavigator p) => p.SelectChildren(XPathNodeType.Element).Cast<XPathNavigator>()); } return from r in source select new XPathResult(type, r, Context, matchingBehavior); } public bool ReadObject(out object value) { if (GetNavigator(false, true, out XPathNavigator result) && result != null) { foreach (IXPathSerializer serializer in Context.Serializers) { if (serializer.ReadObject(this, result, out value)) return true; } } value = null; return false; } public bool WriteObject(object value) { XPathNavigator navigator = GetNavigator(true); foreach (IXPathSerializer serializer in Context.Serializers) { if (serializer.WriteObject(this, navigator, value)) return true; } return false; } private XmlMetadata GetItemQualifedName(Type type, XmlArrayItemAttribute item, Func<Type, XmlMetadata> getXmlMeta, out string name, out string namespaceUri) { name = item.ElementName; namespaceUri = item.Namespace; type = (item.Type ?? type); XmlMetadata xmlMetadata = getXmlMeta(type); if (string.IsNullOrEmpty(name)) { if (xmlMetadata != null) name = xmlMetadata.XmlType.TypeName; else name = GetDataType(type); namespaceUri = null; } namespaceUri = Context.GetEffectiveNamespace(namespaceUri); return xmlMetadata; } public XPathResult CreateNode(Type type, object value, Func<Type, XmlMetadata> getXmlMeta) { string name = null; string namespaceUri = null; string text = null; bool omitPolymorphism = false; XmlMetadata xmlMetadata = getXmlMeta(type); object obj = matchingBehavior; if (xmlMetadata != null) { name = xmlMetadata.XmlType.TypeName; text = xmlMetadata.XmlType.Namespace; } if (value != null) type = ((!(value is IDictionaryAdapter)) ? value.GetType() : ((IDictionaryAdapter)value).Meta.Type); if (xmlMetadata == null) name = GetDataType(type); if (Context.ListItemMeta != null) { XmlArrayItemAttribute xmlArrayItemAttribute = Context.ListItemMeta.FirstOrDefault((XmlArrayItemAttribute li) => (li.Type ?? type) == type); if (xmlArrayItemAttribute != null) { obj = xmlArrayItemAttribute; if (xmlArrayItemAttribute.Type != (Type)null) { type = xmlArrayItemAttribute.Type; xmlMetadata = getXmlMeta(xmlArrayItemAttribute.Type); } else type = type; if (string.IsNullOrEmpty(xmlArrayItemAttribute.ElementName)) { if (xmlMetadata != null) { name = xmlMetadata.XmlType.TypeName; text = xmlMetadata.XmlType.Namespace; } else name = GetDataType(type); } else { name = xmlArrayItemAttribute.ElementName; namespaceUri = xmlArrayItemAttribute.Namespace; } omitPolymorphism = true; } } XPathNavigator xPathNavigator = null; if (IsContainer) { if (Container == null && create != null) Container = create(); if (Container != null) xPathNavigator = Context.AppendElement(name, namespaceUri, Container); } else if (create != null) { xPathNavigator = create(); } if (!string.IsNullOrEmpty(text)) Context.CreateNamespace(null, text, xPathNavigator); XPathResult xPathResult = new XPathResult(type, xPathNavigator, Context, obj); xPathResult.XmlMeta = xmlMetadata; xPathResult.OmitPolymorphism = omitPolymorphism; return xPathResult; } public bool RemoveAt(int index) { return GetNodeAt(null, index).Remove(true); } public bool Remove(bool nillable) { if (Result is XPathNavigator) { XPathNavigator xPathNavigator = (XPathNavigator)Result; if (nillable && IsNullable) { RemoveChildren(xPathNavigator); Context.MakeNil(xPathNavigator); return false; } xPathNavigator.DeleteSelf(); return true; } if (Result is XPathNodeIterator) { bool flag = false; XPathNavigator[] array = ((XPathNodeIterator)Result).Cast<XPathNavigator>().ToArray(); for (int i = 0; i < array.Length; i++) { if (i == 0 && nillable && IsNullable) { RemoveChildren(array[0]); Context.MakeNil(array[0]); flag = true; } else array[i].DeleteSelf(); } if (flag) return false; } Result = null; if (nillable && IsNullable) { XPathNavigator navigator = GetNavigator(true); if (navigator != null) { Context.MakeNil(navigator); Result = navigator; return false; } } return true; } public XPathNavigator RemoveChildren() { XPathNavigator navigator = GetNavigator(true); RemoveChildren(navigator); return navigator; } private static void RemoveChildren(XPathNavigator node) { if (node != null) { IEnumerable<XPathNavigator> source = from XPathNavigator child in node.SelectChildren(XPathNodeType.All) where child.NodeType != XPathNodeType.Namespace select child; XPathNavigator[] array = source.ToArray(); foreach (XPathNavigator xPathNavigator in array) { xPathNavigator.DeleteSelf(); } } } private bool GetNillable(ref XPathNavigator source) { if (source != null && IsNullable && Context.IsNil(source)) { source = null; return false; } return true; } private static string GetDataType(Type type) { if (XmlDataTypes.TryGetValue(type, out string value)) return value; value = type.Name.ToLower(); return value; } } }