/// <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);
        }
Exemple #2
0
 /// <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();
            }
        }
Exemple #5
0
        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);
        }
Exemple #6
0
        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]));
        }
Exemple #7
0
        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);
        }
Exemple #8
0
        /// <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);
            }
        }
Exemple #10
0
 /// <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);
 }
Exemple #11
0
 public virtual List <TDestination> MapList(XPathProcessor source, string collectionNode, string nodeName, bool outputDefault = false)
 {
     return(this.MapList(source, collectionNode, nodeName, this.NamespacePrefix, outputDefault: outputDefault));
 }
Exemple #12
0
 public List <TDestination> MapList(XPathProcessor source, string collectionNode, bool outputDefault = false)
 {
     return(this.MapList(source, collectionNode, this.NodeName, outputDefault));
 }
Exemple #13
0
 /// 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));
 }
Exemple #14
0
 /// <inheritdoc />
 public override TDestination Map(XPathProcessor source)
 {
     return(this.Map(source, this.NodeName));
 }
Exemple #15
0
 /// <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)));
 }