public Component AddShortCut(Component SourceComponent)
        {
            // ---------------------------------------------------------------------
            // Add the source component as a child shortcut component.
            // ---------------------------------------------------------------------
            MyFile.BeginUpdate();
            Component ShortCutComponent = new Component(MyFile, this, SourceComponent);

            MyChildNodes.Add(ShortCutComponent);
            ShortCutComponent.EnsureNameIsUnique();

            // Now we need to go through all child nodes of the shortcut and make
            // them shortcuts as well.
            foreach (Component Child in SourceComponent.ChildNodes)
            {
                ShortCutComponent.AddShortCut(Child);
            }

            MyFile.EndUpdate();
            MyFile.PublishComponentChanged(this);
            CheckOutputFileNode();
            return(ShortCutComponent);
        }
        public Component Add(string Xml, bool AddInitWaterIfNecessary, bool forApsoil)
        {
            // ---------------------------------------------------------------------
            // Add the specified xml as children. The xml might be multiple children
            // i.e. have multiple root nodes and so not valid XML. Add a dummy
            // root node around the xml so that we can parse it. Returns the first
            // child component
            // ---------------------------------------------------------------------
            XmlDocument Doc;

            try
            {
                Doc = new XmlDocument();
                Doc.LoadXml("<dummy>" + Xml + "</dummy>");
                if (AddInitWaterIfNecessary &&
                    Doc.DocumentElement.ChildNodes.Count == 1 &&
                    Doc.DocumentElement.ChildNodes[0].Name.ToLower() == "soil")
                {
                    // A special test for when the user drops a soil on a component node or when
                    // the user pastes a soil node. We want to make sure there are <initwater> and
                    // <initnitrogen> nodes.
                    XmlNode SoilNode         = Doc.DocumentElement.ChildNodes[0];
                    XmlNode InitWaterNode    = XmlHelper.FindByType(SoilNode, "InitWater");
                    XmlNode InitNitrogenNode = XmlHelper.FindByType(SoilNode, "InitNitrogen");
                    XmlNode SoilSampleNode   = XmlHelper.FindByType(SoilNode, "Sample");
                    if (InitWaterNode == null && InitNitrogenNode == null && SoilSampleNode == null && !forApsoil)
                    {
                        // Default to a full profile
                        InitWaterNode = SoilNode.AppendChild(SoilNode.OwnerDocument.CreateElement("InitialWater"));
                        XmlHelper.SetName(InitWaterNode, "InitialWater");
                        InitWaterNode.InnerXml =
                            "<FractionFull>1</FractionFull>" +
                            "<PercentMethod>FilledFromTop</PercentMethod>";

                        InitNitrogenNode = SoilNode.AppendChild(SoilNode.OwnerDocument.CreateElement("Sample"));
                        XmlHelper.SetName(InitNitrogenNode, "InitialNitrogen");

                        // If possible, set up nitrogen node based on any existing Analysis node
                        // Otherwise, use water node to initialise the layer structure
                        // If that doesn't work, just add 1 dummy layer

                        // Similarly, transfer values for pH and EC, if they exist.

                        XmlNode AnalysisNode  = XmlHelper.FindByType(SoilNode, "Analysis");
                        XmlNode WaterNode     = XmlHelper.FindByType(SoilNode, "Water");
                        string  Thickness     = "<Thickness units=\"mm\">100</Thickness>";
                        XmlNode ThicknessNode = null;
                        if (AnalysisNode != null)
                        {
                            ThicknessNode = XmlHelper.Find(AnalysisNode, "Thickness");
                        }
                        if (ThicknessNode == null && WaterNode != null)
                        {
                            ThicknessNode = XmlHelper.Find(WaterNode, "Thickness");
                        }
                        if (ThicknessNode != null)
                        {
                            Thickness = ThicknessNode.OuterXml;
                        }

                        InitNitrogenNode.InnerXml = "<Date type=\"date\" description=\"Sample date:\" />" +
                                                    Thickness +
                                                    "  <NO3Units>ppm</NO3Units>" +
                                                    "  <NH4Units>ppm</NH4Units>" +
                                                    "  <SWUnits>Volumetric</SWUnits>" +
                                                    "  <OCUnits>Total</OCUnits>" +
                                                    "  <PHUnits>Water</PHUnits>";
                    }
                }
            }
            catch (Exception)
            {
                return(null);
            }

            Component FirstChildComponent = null;

            MyFile.BeginUpdate();
            foreach (XmlNode Child in Doc.DocumentElement.ChildNodes)
            {
                if (Types.Instance.AllowComponentAdd(Child.Name, Type) || Type == "factor" || Type == "factorComplex")
                {
                    Component ChildComponent = new Component(MyFile, this);
                    MyChildNodes.Add(ChildComponent);
                    ChildComponent.Read(Child);
                    ChildComponent.ResolveShortcuts();
                    ChildComponent.EnsureNameIsUnique();
                    if (FirstChildComponent == null)
                    {
                        FirstChildComponent = ChildComponent;
                    }
                }
            }
            MyFile.EndUpdate();
            MyFile.PublishComponentChanged(this);
            return(FirstChildComponent);
        }