/// <summary> /// Maps a list of simple values into a collection /// </summary> /// <typeparam name="T">Type of value to return</typeparam> /// <param name="source">XPathProcessor to use</param> /// <param name="collectionNode">Collection node name (may be null)</param> /// <param name="nodeName">Node name to use</param> /// <param name="func">Function to access the data from the XPathProcessor, e.g. x => x.ToInt(CurrentXPath)</param> /// <returns>List of values</returns> public static List <T> MapList <T>(this XPathProcessor source, string collectionNode, string nodeName, Func <XPathProcessor, T> func) { if (!string.IsNullOrEmpty(collectionNode)) { source.Push(collectionNode); } var list = new List <T>(); var index = 1; while (source.HasElement(nodeName, index: index)) { source.Push(nodeName, index: index); try { list.Add(func(source)); index++; } finally { source.Pop(); } } if (!string.IsNullOrEmpty(collectionNode)) { source.Pop(); } return(list); }
/// <summary> /// Registers the namespaces against the processor if it doesn't exist /// </summary> /// <param name="source"></param> /// <returns>Empty string if no namespace, existing prefix if already defined, namespacePrefix otherwise</returns> protected void RegisterNamespaces(XPathProcessor source) { foreach (var nst in this.namespaces) { this.RegisterNamespace(source, nst.Item1, nst.Item2); } }
/// <copydocfrom cref="IXmlMapper{T, D}.Map(T, string, string, bool)" /> public TDestination Map(XPathProcessor source, string nodeName, string xmlNamespace = "", bool outputDefault = false) { RegisterNamespace(source, NamespacePrefix, Namespace); // Push both the node and the namespace - presumption that the namespace applies to the node source.Push(nodeName, Namespace); try { if (!source.CurrentNode()) { return(null); } RegisterNamespace(source, XsiPrefix, XsiNamespace); var xmlType = source.ToString("type", XsiPrefix, isAttribute: true); TDestination destination; // This mapper can handle it if there's no type specified or it's our type if (string.IsNullOrEmpty(xmlType) || string.IsNullOrEmpty(XmlType)) { destination = CreateAndMap(source); } else { var t = XmlTypeInfo(source, xmlType); if (XmlTypeNamespace == t.Item1 && XmlType == t.Item2) { destination = CreateAndMap(source); } else { // Otherwise, pass off to the engine // NB Use the current namespace for the node name, not the target mapper's if (!nodeName.Contains(":")) { nodeName = string.Format("{0}:{1}", NamespacePrefix, nodeName); } try { destination = Engine.Map <XPathProcessor, TDestination>(source, nodeName, t.Item1, t.Item2); } catch (XmlTypeMappingException) { // try to map with our base engine destination = this.CreateAndMap(source); } } } return(destination); } finally { // Make sure we unwind the stack in all cases source.Pop(); } }
protected TDestination Map(XPathProcessor source, string nodeName, string xmlNamespace, string xmlPrefix, int index) { RegisterNamespace(source, NamespacePrefix, Namespace); // Namespace and node provide context, however the prefix if present overrides the node's actual namespace source.Push(nodeName, Namespace, xmlPrefix, index); try { if (!source.CurrentNode()) { return(null); } var xmlType = string.Empty; RegisterNamespace(source, XsiPrefix, XsiNamespace); xmlType = source.ToString("type", XsiPrefix, isAttribute: true); TDestination destination; // This mapper can handle it if there's no type specified or it's our type or if it is the base mapper for an unknown type if (string.IsNullOrEmpty(xmlType) || string.IsNullOrEmpty(XmlType)) { destination = CreateAndMap(source); } else { var t = XmlTypeInfo(source, xmlType); if (t.Item1 == XmlTypeNamespace && t.Item2 == XmlType) { // We're responsible destination = CreateAndMap(source); } else { // Need a mapper for this xsi:type try { destination = XsiMapper(source, nodeName, t.Item1, t.Item2, index); } catch (XmlTypeMappingException) { // if we don't get one try with this base one destination = this.CreateAndMap(source); } } } return(destination); } finally { // Make sure we unwind the stack in all cases source.Pop(); } }
public virtual List <TDestination> MapList(XPathProcessor source, string collectionNode, string nodeName, string collectionNodeNamespacePrefix = "", string collectionItemNodeNamespacePrefix = "", bool outputDefault = false) { // Default namespace this.RegisterNamespace(source, this.NamespacePrefix, this.Namespace); string collNamespace; var list = new List <TDestination>(); if (string.IsNullOrWhiteSpace(collectionNodeNamespacePrefix)) { // It's the same as normal collectionNodeNamespacePrefix = this.NamespacePrefix; collNamespace = this.Namespace; } else { // Look it up. collNamespace = source.LookupNamespace(collectionNodeNamespacePrefix); if (string.IsNullOrWhiteSpace(collNamespace)) { throw new MappingException(string.Format("No namespace registered for {0}", collectionNodeNamespacePrefix)); } } if (!string.IsNullOrEmpty(collectionNode)) { source.Push(collectionNode, collNamespace, collectionNodeNamespacePrefix); } if (string.IsNullOrEmpty(nodeName)) { nodeName = this.NodeName; } var index = 1; TDestination item; do { item = this.Map(source, nodeName, string.Empty, collectionItemNodeNamespacePrefix, index++); if (item != null) { list.Add(item); } }while (item != null); if (!string.IsNullOrEmpty(collectionNode)) { source.Pop(); } return(list); }
private Tuple <string, string> XmlTypeInfo(XPathProcessor source, string xmlType) { var parts = xmlType.Split(':'); if (parts.GetUpperBound(0) == 0) { return(new Tuple <string, string>(source.CurrentNamespace, parts[0])); } // Need the namespace not the registered prefix var ns = source.LookupNamespace(parts[0]); return(new Tuple <string, string>(ns, parts[1])); }
private TDestination CreateAndMap(XPathProcessor source) { var destination = this.CreateDestination(); var pb = destination as INullableProperties; if (pb != null) { pb.NullProperties.Loading = true; } this.Map(source, destination); if (pb != null) { pb.NullProperties.Loading = false; } return(destination); }
/// <summary> /// Map an entity for a particular xsi:type. /// </summary> /// <param name="source">Processor to use</param> /// <param name="nodeName">Node name to use.</param> /// <param name="xmlNamespace">XML namespace to use.</param> /// <param name="xmlType">XML type to use</param> /// <param name="index">Index to use.</param> /// <returns>A new instance of the TDestination class mapped from the source.</returns> private TDestination XsiMapper(XPathProcessor source, string nodeName, string xmlNamespace, string xmlType, int index) { // Unwind the current node position, we're about to do the same again. source.Pop(); try { // NB Use the current namespace for the node name, not the target mapper's var destination = this.Engine.Map <XPathProcessor, TDestination>( source, nodeName, xmlNamespace, xmlType, this.NamespacePrefix, index); return(destination); } finally { // Put it back where it was source.Push(nodeName, xmlNamespace, this.NamespacePrefix, index); } }
/// <summary> /// Convert XML to an entity. /// </summary> /// <typeparam name="T"></typeparam> /// <param name="processor"></param> /// <param name="element"></param> /// <returns></returns> protected T FromXml <T>(XPathProcessor processor, XElement element) { try { var version = this.VersionDetector.DetectSchemaVersion(element); if (version == string.Empty) { throw new MappingException("Could not detect schema version"); } var entity = this.Engine(version).Map <XPathProcessor, T>(processor); return(entity); } catch (MappingException) { // Lower level returned mapping exception, don't add anything. throw; } catch (Exception ex) { throw new MappingException("Could not convert document to entity: " + typeof(T).Name, ex); } }
/// <summary> /// Registers the namespace against the processor if it doesn't exist /// </summary> /// <param name="source"></param> /// <param name="xmlPrefix">Prefix to use as an alias for the XML namespace</param> /// <param name="xmlNamespace">XML namespace to register</param> /// <returns>Empty string if no namespace, existing prefix if already defined, namespacePrefix otherwise</returns> protected void RegisterNamespace(XPathProcessor source, string xmlPrefix, string xmlNamespace) { source.RegisterNamespace(xmlPrefix, xmlNamespace); }
public virtual List <TDestination> MapList(XPathProcessor source, string collectionNode, string nodeName, bool outputDefault = false) { return(this.MapList(source, collectionNode, nodeName, this.NamespacePrefix, outputDefault: outputDefault)); }
public List <TDestination> MapList(XPathProcessor source, string collectionNode, bool outputDefault = false) { return(this.MapList(source, collectionNode, this.NodeName, outputDefault)); }
/// NOTE: No defaults as we can't enforce implementation - caller determines passed values - C# standard object IXmlMapper <XPathProcessor> .Map(XPathProcessor source, string nodeName, string xmlNamespace, string xmlPrefix, int index) { return(this.Map(source, nodeName, xmlNamespace, xmlPrefix, index)); }
/// <inheritdoc /> public override TDestination Map(XPathProcessor source) { return(this.Map(source, this.NodeName)); }
/// <summary> /// Uses a <see cref="XPathProcessor" /> to populate an object based on the mapping. /// </summary> /// <param name="processor">XPathProcessor to use</param> /// <param name="value">Object to populate</param> public void FromXml(XPathProcessor processor, object value) { throw new NotImplementedException("Not Implemented"); }
/// <summary> /// Maps a list of string values into a collection /// </summary> /// <param name="source">XPathProcessor to use</param> /// <param name="collectionNode">Collection node name (may be null)</param> /// <param name="nodeName">Node name to use</param> /// <returns>List of strings values</returns> public static List <string> MapList(this XPathProcessor source, string collectionNode, string nodeName) { return(source.MapList(collectionNode, nodeName, x => x.ToString(CurrentXPath))); }