private XElement PopulateTree(XElement current, Func <DataMapping, IEnumerable <XElement> > parentGetter, Func <DataMapping, string> calculatedGetter)
        {
            calculatedGetter = calculatedGetter ?? (Func <DataMapping, string>)(m => m.Value);

            MappedType             lastType = null;
            IEnumerable <XElement> parents  = Enumerable.Repeat(current, 1);

            foreach (var mapping in _mappings)
            {
                if (mapping.Type != lastType)
                {
                    if (lastType != null)
                    {
                        if (mapping.Type.ItemType.Relationship == null)
                        {
                            current = current.AddAndReturn(new XElement("related_id"));
                        }
                        else
                        {
                            current = current.AddAndReturn(new XElement("Relationships"));
                        }
                    }

                    parents = null;
                    if (parentGetter != null)
                    {
                        parents = parentGetter.Invoke(mapping);
                    }

                    if (parents == null)
                    {
                        current = current.AddAndReturn(new XElement("Item",
                                                                    new XAttribute("type", mapping.Type.ItemType.Name),
                                                                    new XAttribute("typeid", mapping.Type.ItemType.Id)
                                                                    ));
                        parents = Enumerable.Repeat(current, 1);
                    }

                    var id = _mappings.FirstOrDefault(m => m.Type == mapping.Type && m.Property != null && m.Property.Name == "id");
                    if (id != null)
                    {
                        foreach (var parent in parents)
                        {
                            current.Add(new XAttribute("id", id.IsCalculated ? "{" + id.Value + "}" : id.Value));
                        }
                    }
                }

                if (mapping.Property != null)
                {
                    foreach (var parent in parents)
                    {
                        switch (mapping.Property.Type)
                        {
                        case PropertyType.Item:
                            parent.Add(new XElement(mapping.Property.Name,
                                                    new XElement("Item", new XAttribute("type", mapping.Property.ItemSource.Name), new XAttribute("action", "get"),
                                                                 new XElement("keyed_name",
                                                                              mapping.IsCalculated
                      ? (object)new XElement(_nsXsl + "value-of", new XAttribute("select", calculatedGetter.Invoke(mapping)))
                      : mapping.Value
                                                                              )
                                                                 )
                                                    ));
                            break;

                        case PropertyType.Date:
                            parent.Add(new XElement(mapping.Property.Name,
                                                    mapping.IsCalculated
                  ? (object)new XElement(_nsXsl + "value-of", new XAttribute("select", "arasx:FormatDate(" + calculatedGetter.Invoke(mapping) + ", 's')"))
                  : (string.IsNullOrEmpty(mapping.Value) ? "" : DateTime.Parse(mapping.Value).ToString("s"))
                                                    ));
                            break;

                        default:
                            parent.Add(new XElement(mapping.Property.Name,
                                                    mapping.IsCalculated ? (object)new XElement(_nsXsl + "value-of", new XAttribute("select", calculatedGetter.Invoke(mapping))) : mapping.Value
                                                    ));
                            break;
                        }
                    }
                }

                lastType = mapping.Type;
            }
            return(current);
        }