예제 #1
0
파일: Soil.cs 프로젝트: fai04d/DSSATtoAPSIM
        public static void ConvertSoil()
        {
            XmlDocument doc = new XmlDocument();
            //StreamReader input = new StreamReader(@"C:\Users\fai04d\Desktop\WI.SOL");
            StreamReader input = new StreamReader(@"C:\temp\EB.SOL");
            XmlNode soil = null;
            string line;

            XmlElement root = doc.CreateElement("Folder");
            root.SetAttribute("version", "36");
            doc.AppendChild(root);

            while ((line = input.ReadLine()) != null)
            {
                if (line.StartsWith("*"))
                {
                    soil = XmlHelper.CreateNode(doc, "Soil", "");
                    try
                    {
                        XmlHelper.SetAttribute(soil, "name", line.Substring(1, 10));
                        Console.WriteLine("Processing: " + line.Substring(1, 10));
                    }
                    catch
                    {
                        XmlHelper.SetAttribute(soil, "name", "Soil");
                        Console.WriteLine("Processing: Soil");
                    }

                }
                else if (line.StartsWith("@SITE"))
                {
                    SoilProperties sp = new SoilProperties();

                    line = input.ReadLine(); //line 3

                    sp.country = line.Substring(13, 10).Trim();
                    sp.lat = line.Substring(26, 7).Trim();
                    sp.lon = line.Substring(35, 7).Trim();
                    sp.name = line.Substring(43).Trim();

                    input.ReadLine(); //line 4
                    line = input.ReadLine().Replace("-99", "   "); //line 5
                    sp.scom = line.Substring(0, 7).Trim();
                    sp.salb = line.Substring(6, 6).Trim();
                    sp.slu1 = line.Substring(12, 6).Trim();
                    sp.sldr = line.Substring(18, 6).Trim();
                    sp.slro = line.Substring(24, 6).Trim();
                    sp.slnf = line.Substring(30, 6).Trim();
                    sp.slpf = line.Substring(36, 6).Trim();

                    input.ReadLine(); //line 6
                    line = input.ReadLine().Replace("-99", "   "); //line 7
                    int i = 0;
                    do //1st block of layer lines
                    {
                        Layer l = new Layer();
                        l.depth = line.Substring(0, 6).Trim();
                        l.slmh = line.Substring(6, 7).Trim();
                        l.slll = line.Substring(13, 6).Trim();
                        l.sdul = line.Substring(19, 6).Trim();
                        l.ssat = line.Substring(25, 6).Trim();
                        l.srgf = line.Substring(31, 6).Trim();
                        l.ssks = line.Substring(37, 6).Trim();
                        l.sbdm = line.Substring(43, 6).Trim();
                        l.sloc = line.Substring(49, 6).Trim();
                        l.slcl = line.Substring(55, 6).Trim();
                        l.slsi = line.Substring(61, 6).Trim();
                        l.slcf = line.Substring(67, 6).Trim();
                        l.slni = line.Substring(73, 6).Trim();
                        l.slhw = line.Substring(79, 6).Trim();
                        l.slhb = line.Substring(85, 6).Trim();
                        l.scec = line.Substring(91, 6).Trim();
                        l.sadc = line.Substring(97).Trim();
                        sp.layers.Add(l);
                        line = input.ReadLine().Replace("-99.0", "     ");
                    } while (line.Length > 0);     // (!(line.Contains("@")));

                    /*       line = input.ReadLine().Replace("-99.0", "     "); //line 11
                           do //2nd block of layer lines. No error check. Assumes same number of layers (which is true, if not then the soil data is wrong, but we don't handle that case)
                           {
                               Layer l = sp.layers[i];
                               l.slpx = line.Substring(6, 7).Trim();
                               l.slpt = line.Substring(13, 6).Trim();
                               l.slpo = line.Substring(19, 6).Trim();
                               l.caco3 = line.Substring(25, 6).Trim();
                               l.slal = line.Substring(31, 6).Trim();
                               l.slfe = line.Substring(37, 6).Trim();
                               l.slmn = line.Substring(43, 6).Trim();
                               l.slbs = line.Substring(49, 6).Trim();
                               l.slpa = line.Substring(55, 6).Trim();
                               l.slpb = line.Substring(61, 6).Trim();
                               l.slke = line.Substring(67, 6).Trim();
                               l.slmg = line.Substring(73, 6).Trim();
                               l.slna = line.Substring(79, 6).Trim();
                               l.slsu = line.Substring(85, 6).Trim();
                               l.slec = line.Substring(91, 6).Trim();
                               l.slca = line.Substring(97).Trim();
                               i++;
                               line = input.ReadLine();
                           } while (line.Length > 0);*/
                    //////read finished

                    XmlHelper.SetValue(soil, "Country", sp.country);
                    XmlHelper.SetValue(soil, "LocalName", "");
                    XmlHelper.SetValue(soil, "Site", "");
                    XmlHelper.SetValue(soil, "Region", "");
                    XmlHelper.SetValue(soil, "SoilType", sp.name);
                    XmlHelper.SetValue(soil, "NearestTown", "");
                    XmlHelper.SetValue(soil, "NaturalVegetation", "");
                    XmlHelper.SetValue(soil, "State", "");
                    XmlHelper.SetValue(soil, "ApsoilNumber", "");
                    XmlHelper.SetValue(soil, "Latitude", sp.lat);
                    XmlHelper.SetValue(soil, "Longitude", sp.lon);
                    XmlHelper.SetValue(soil, "LocationAccuracy", "");
                    XmlHelper.SetValue(soil, "DataSource", "Romero, C.C., Hoogenboom, G., Baigorria, G.A., Koo, J., Gijsman, A.J., Wood, S., 2012. Reanalysis of a global soil database for crop and environmental modeling. Environmental Modelling & Software 35, 163-170.  https://harvestchoice.wufoo.com/forms/download-wisol.");
                    XmlHelper.SetValue(soil, "Comments", "You will need to add crops to this soil before running simulations.");

                    //Initial Water
                    XmlNode initWater = XmlHelper.CreateNode(doc, "InitialWater", "");
                    XmlHelper.SetAttribute(initWater, "name", "Initial Water");
                    XmlHelper.SetValue(initWater, "FractionFull", "1");
                    XmlHelper.SetValue(initWater, "PercentMethod", "FilledFromTop");

                    //Water
                    XmlNode water = XmlHelper.CreateNode(doc, "Water", "");
                    XmlNode attr;

                    int lastLayer = 0;
                    XmlNode thickness = XmlHelper.CreateNode(doc, "Thickness", "");
                    for (int k = 0; k < sp.layers.Count; k++) //set up layers
                    {
                        XmlNode dbl = XmlHelper.CreateNode(doc, "double", "");
                        int layerDepth = (Int32.Parse(sp.layers[k].depth) - lastLayer) * 10;
                        lastLayer = Int32.Parse(sp.layers[k].depth);
                        XmlHelper.SetValue(dbl, "", layerDepth.ToString());
                        thickness.AppendChild(dbl);
                    }
                    water.AppendChild(thickness);

                    XmlNode bd = XmlHelper.CreateNode(doc, "BD", "");
                    for (int k = 0; k < sp.layers.Count; k++) //set up layers
                    {
                        XmlNode dbl = XmlHelper.CreateNode(doc, "double", "");
                        XmlHelper.SetValue(dbl, "", sp.layers[k].sbdm);
                        bd.AppendChild(dbl);
                    }
                    water.AppendChild(bd);

                    XmlNode airDry = XmlHelper.CreateNode(doc, "AirDry", "");
                    for (int k = 0; k < sp.layers.Count; k++) //set up layers
                    {
                        XmlNode dbl = XmlHelper.CreateNode(doc, "double", "");
                        double airdry = Convert.ToDouble(sp.layers[k].slll) / 3;
                        XmlHelper.SetValue(dbl, "", airdry.ToString("#.##"));
                        airDry.AppendChild(dbl);
                    }
                    water.AppendChild(airDry);

                    XmlNode ll15 = XmlHelper.CreateNode(doc, "LL15", "");
                    for (int k = 0; k < sp.layers.Count; k++) //set up layers
                    {
                        XmlNode dbl = XmlHelper.CreateNode(doc, "double", "");
                        XmlHelper.SetValue(dbl, "", sp.layers[k].slll);
                        ll15.AppendChild(dbl);
                    }
                    water.AppendChild(ll15);

                    XmlNode dul = XmlHelper.CreateNode(doc, "DUL", "");
                    for (int k = 0; k < sp.layers.Count; k++) //set up layers
                    {
                        XmlNode dbl = XmlHelper.CreateNode(doc, "double", "");
                        XmlHelper.SetValue(dbl, "", sp.layers[k].sdul);
                        dul.AppendChild(dbl);
                    }
                    water.AppendChild(dul);

                    XmlNode sat = XmlHelper.CreateNode(doc, "SAT", "");
                    for (int k = 0; k < sp.layers.Count; k++) //set up layers
                    {
                        XmlNode dbl = XmlHelper.CreateNode(doc, "double", "");
                        XmlHelper.SetValue(dbl, "", sp.layers[k].ssat);
                        sat.AppendChild(dbl);
                    }
                    water.AppendChild(sat);

                    XmlNode ks = XmlHelper.CreateNode(doc, "KS", "");
                    for (int k = 0; k < sp.layers.Count; k++) //set up layers
                    {
                        XmlNode dbl = XmlHelper.CreateNode(doc, "double", "");
                        XmlHelper.SetValue(dbl, "", sp.layers[k].ssks);
                        ks.AppendChild(dbl);
                    }
                    water.AppendChild(ks);

                    ///SoilWat
                    XmlNode soilWat = XmlHelper.CreateNode(doc, "SoilWater", "");
                    XmlHelper.SetValue(soilWat, "SummerCona", "3"); //No value available in WI.SOL
                    XmlHelper.SetValue(soilWat, "SummerU", sp.slu1); //Using SLU1 from WI.SOL. Unsure if this is correct.
                    XmlHelper.SetValue(soilWat, "SummerDate", sp.lat.Contains('-') ? "1-Nov" : "1-Apr");
                    XmlHelper.SetValue(soilWat, "WinterCona", "3");
                    XmlHelper.SetValue(soilWat, "WinterU", sp.slu1);
                    XmlHelper.SetValue(soilWat, "WinterDate", sp.lat.Contains('-') ? "1-Apr" : "1-Nov");
                    XmlHelper.SetValue(soilWat, "DiffusConst", "");
                    XmlHelper.SetValue(soilWat, "DiffusSlope", "");
                    XmlHelper.SetValue(soilWat, "Salb", sp.salb);
                    XmlHelper.SetValue(soilWat, "Cn2Bare", sp.slro);
                    XmlHelper.SetValue(soilWat, "CnRed", "");
                    XmlHelper.SetValue(soilWat, "CnCov", "");
                    XmlHelper.SetValue(soilWat, "Slope", "");
                    XmlHelper.SetValue(soilWat, "DischargeWidth", "");
                    XmlHelper.SetValue(soilWat, "CatchmentArea", "");
                    XmlHelper.SetValue(soilWat, "MaxPond", "");

                    lastLayer = 0;
                    thickness = XmlHelper.CreateNode(doc, "Thickness", "");
                    for (int k = 0; k < sp.layers.Count; k++)
                    {
                        XmlNode dbl = XmlHelper.CreateNode(doc, "double", "");
                        int layerDepth = Int32.Parse(sp.layers[k].depth) - lastLayer;
                        lastLayer = Int32.Parse(sp.layers[k].depth);
                        XmlHelper.SetValue(dbl, "", layerDepth.ToString() + "0");
                        thickness.AppendChild(dbl);
                    }
                    soilWat.AppendChild(thickness);

                    XmlNode swcon = XmlHelper.CreateNode(doc, "SWCON", "");
                    for (int k = 0; k < sp.layers.Count; k++)
                    {
                        XmlNode dbl = XmlHelper.CreateNode(doc, "double", "");
                        XmlHelper.SetValue(dbl, "", "0.5");
                        swcon.AppendChild(dbl);
                    }
                    soilWat.AppendChild(swcon);

                    //SoilOrganicMatter
                    int[] depths = new int[sp.layers.Count];
                    double[] carbons = new double[sp.layers.Count];
                    double[] nitrogens = new double[sp.layers.Count];

                    try //handle case where no OC data
                    {
                        for (int k = 0; k < sp.layers.Count; k++)
                        {
                            depths[k] = Convert.ToInt32(sp.layers[k].depth);
                            carbons[k] = Convert.ToDouble(sp.layers[k].sloc);
                            nitrogens[k] = Convert.ToDouble(sp.layers[k].slni);
                        }
                    }
                    catch (Exception e)
                    {
                        carbons = null;
                    }

                    XmlNode soilOM = XmlHelper.CreateNode(doc, "SoilOrganicMatter", "");
                    XmlHelper.SetValue(soilOM, "RootCn", "");
                    XmlHelper.SetValue(soilOM, "RootWt", "");
                    XmlHelper.SetValue(soilOM, "EnrACoeff", "");
                    XmlHelper.SetValue(soilOM, "EnrBCoeff", "");

                    double CNratio = 0;
                    if (carbons != null) //handle case where no OC data
                    {

                        double cOC50 = LogRegression(depths, carbons, 50);
                        double nOC50 = LogRegression(depths, nitrogens, 50);
                        double cErt = carbons[0] - cOC50;
                        double nErt = nitrogens[0] - nOC50;
                        CNratio = cErt / nErt;
                    }

                    XmlHelper.SetValue(soilOM, "SoilCn", CNratio == 0 ? "" : CNratio.ToString("#.##")); //if 0, no carbon data

                    lastLayer = 0;
                    double[] fInert = new double[sp.layers.Count];
                    double[] fBiom = new double[sp.layers.Count];
                    for (int k = 0; k < sp.layers.Count; k++)
                    {

                        // Calculate FBIOM and FINERT

                        if (carbons != null) //handle case where no OC data
                        {
                            if (depths[k] > 50)
                                fInert[k] = 1;
                            else
                            {
                                double cOC50 = LogRegression(depths, carbons, 50);
                                double nOC50 = LogRegression(depths, nitrogens, 50);
                                double cErt = carbons[k] - cOC50;
                                double nErt = nitrogens[0] - nOC50;
                                double cFert = cErt / carbons[k];
                                fInert[k] = 1 - cFert;
                                if (fInert[k] < 0)
                                    fInert[k] = 0;
                                else if (fInert[k] > 1)
                                    fInert[k] = 1;
                            }
                        }
                        if (Convert.ToInt16(sp.layers[k].depth) <= 15)
                            fBiom[k] = 0.04;
                        else if (Convert.ToInt16(sp.layers[k].depth) <= 60)
                            fBiom[k] = 0.02;
                        else
                            fBiom[k] = 0.01;
                    }

                    lastLayer = 0;
                    thickness = XmlHelper.CreateNode(doc, "Thickness", "");
                    for (int k = 0; k < sp.layers.Count; k++)
                    {
                        XmlNode dbl = XmlHelper.CreateNode(doc, "double", "");
                        int layerDepth = Int32.Parse(sp.layers[k].depth) - lastLayer;
                        lastLayer = Int32.Parse(sp.layers[k].depth);
                        XmlHelper.SetValue(dbl, "", layerDepth.ToString() + "0");
                        thickness.AppendChild(dbl);
                    }
                    soilOM.AppendChild(thickness);

                    XmlNode oc = XmlHelper.CreateNode(doc, "OC", "");
                    for (int k = 0; k < sp.layers.Count; k++)
                    {
                        XmlNode dbl = XmlHelper.CreateNode(doc, "double", "");
                        XmlHelper.SetValue(dbl, "", sp.layers[k].sloc);
                        oc.AppendChild(dbl);
                    }
                    soilOM.AppendChild(oc);

                    XmlNode fbiom = XmlHelper.CreateNode(doc, "FBiom", "");
                    for (int k = 0; k < sp.layers.Count; k++)
                    {
                        XmlNode dbl = XmlHelper.CreateNode(doc, "double", "");
                        XmlHelper.SetValue(dbl, "", fBiom[k].ToString("#.##"));
                        fbiom.AppendChild(dbl);
                    }
                    soilOM.AppendChild(fbiom);

                    XmlNode fin = XmlHelper.CreateNode(doc, "FInert", "");
                    for (int k = 0; k < sp.layers.Count; k++)
                    {
                        XmlNode dbl = XmlHelper.CreateNode(doc, "double", "");
                        XmlHelper.SetValue(dbl, "", carbons == null ? "" : fInert[k].ToString("#.##"));
                        fin.AppendChild(dbl);
                    }
                    soilOM.AppendChild(fin);

                    /// Analysis
                    XmlNode analysis = XmlHelper.CreateNode(doc, "Analysis", "");
                    lastLayer = 0;
                    thickness = XmlHelper.CreateNode(doc, "Thickness", "");
                    for (int k = 0; k < sp.layers.Count; k++)
                    {
                        XmlNode dbl = XmlHelper.CreateNode(doc, "double", "");
                        int layerDepth = Int32.Parse(sp.layers[k].depth) - lastLayer;
                        lastLayer = Int32.Parse(sp.layers[k].depth);
                        XmlHelper.SetValue(dbl, "", layerDepth.ToString() + "0");
                        thickness.AppendChild(dbl);
                    }
                    analysis.AppendChild(thickness);

                    XmlNode munsell = XmlHelper.CreateNode(doc, "MunsellColour", "");
                    for (int k = 0; k < sp.layers.Count; k++)
                    {
                        XmlNode dbl = XmlHelper.CreateNode(doc, "string", "");
                        XmlHelper.SetValue(dbl, "", sp.scom);
                        munsell.AppendChild(dbl);
                    }
                    analysis.AppendChild(munsell);

                    XmlNode ec = XmlHelper.CreateNode(doc, "EC", "");
                    for (int k = 0; k < sp.layers.Count; k++)
                    {
                        XmlNode dbl = XmlHelper.CreateNode(doc, "double", "");
                        XmlHelper.SetValue(dbl, "", sp.layers[k].slec);
                        ec.AppendChild(dbl);
                    }
                    analysis.AppendChild(ec);

                    XmlNode ph = XmlHelper.CreateNode(doc, "PH", "");
                    for (int k = 0; k < sp.layers.Count; k++)
                    {
                        XmlNode dbl = XmlHelper.CreateNode(doc, "double", "");
                        XmlHelper.SetValue(dbl, "", sp.layers[k].slhw);
                        ph.AppendChild(dbl);
                    }
                    analysis.AppendChild(ph);

                    XmlNode Ca = XmlHelper.CreateNode(doc, "Ca", "");
                    for (int k = 0; k < sp.layers.Count; k++)
                    {
                        XmlNode dbl = XmlHelper.CreateNode(doc, "double", "");
                        XmlHelper.SetValue(dbl, "", sp.layers[k].slca);
                        Ca.AppendChild(dbl);
                    }
                    analysis.AppendChild(Ca);

                    XmlNode Mg = XmlHelper.CreateNode(doc, "Mg", "");
                    for (int k = 0; k < sp.layers.Count; k++)
                    {
                        XmlNode dbl = XmlHelper.CreateNode(doc, "double", "");
                        XmlHelper.SetValue(dbl, "", sp.layers[k].slmg);
                        Mg.AppendChild(dbl);
                    }
                    analysis.AppendChild(Mg);

                    XmlNode Na = XmlHelper.CreateNode(doc, "Na", "");
                    for (int k = 0; k < sp.layers.Count; k++)
                    {
                        XmlNode dbl = XmlHelper.CreateNode(doc, "double", "");
                        XmlHelper.SetValue(dbl, "", sp.layers[k].slna);
                        Na.AppendChild(dbl);
                    }
                    analysis.AppendChild(Na);

                    XmlNode K = XmlHelper.CreateNode(doc, "K", "");
                    for (int k = 0; k < sp.layers.Count; k++)
                    {
                        XmlNode dbl = XmlHelper.CreateNode(doc, "double", "");
                        XmlHelper.SetValue(dbl, "", sp.layers[k].slke);
                        K.AppendChild(dbl);
                    }
                    analysis.AppendChild(K);

                    XmlNode Mn = XmlHelper.CreateNode(doc, "Mn", "");
                    for (int k = 0; k < sp.layers.Count; k++)
                    {
                        XmlNode dbl = XmlHelper.CreateNode(doc, "double", "");
                        XmlHelper.SetValue(dbl, "", sp.layers[k].slmn);
                        Mn.AppendChild(dbl);
                    }
                    analysis.AppendChild(Mn);

                    XmlNode Al = XmlHelper.CreateNode(doc, "Al", "");
                    for (int k = 0; k < sp.layers.Count; k++)
                    {
                        XmlNode dbl = XmlHelper.CreateNode(doc, "double", "");
                        XmlHelper.SetValue(dbl, "", sp.layers[k].slal);
                        Al.AppendChild(dbl);
                    }
                    analysis.AppendChild(Al);

                    XmlNode PSSilt = XmlHelper.CreateNode(doc, "ParticleSizeSilt", "");
                    for (int k = 0; k < sp.layers.Count; k++)
                    {
                        XmlNode dbl = XmlHelper.CreateNode(doc, "double", "");
                        XmlHelper.SetValue(dbl, "", sp.layers[k].slsi);
                        PSSilt.AppendChild(dbl);
                    }
                    analysis.AppendChild(PSSilt);

                    XmlNode PSClay = XmlHelper.CreateNode(doc, "ParticleSizeClay", "");
                    for (int k = 0; k < sp.layers.Count; k++)
                    {
                        XmlNode dbl = XmlHelper.CreateNode(doc, "double", "");
                        XmlHelper.SetValue(dbl, "", sp.layers[k].slcl);
                        PSClay.AppendChild(dbl);
                    }
                    analysis.AppendChild(PSClay);

                    XmlNode PSSand = XmlHelper.CreateNode(doc, "ParticleSizeSand", "");
                    for (int k = 0; k < sp.layers.Count; k++)
                    {
                        XmlNode dbl = XmlHelper.CreateNode(doc, "double", "");
                        int psSilt = 0, psClay = 0, psSand = 0;
                        if (Int32.TryParse(sp.layers[k].slsi, out psSilt) &&
                            Int32.TryParse(sp.layers[k].slcl, out psClay))
                            psSand = 100 - psSilt - psClay;
                        XmlHelper.SetValue(dbl, "", psSand.ToString());
                        PSSand.AppendChild(dbl);
                    }
                    analysis.AppendChild(PSSand);

                    /// Initial Nitrogen
                    XmlNode initN = XmlHelper.CreateNode(doc, "Sample", "");
                    XmlHelper.SetAttribute(initN, "name", "Initial nitrogen");
                    XmlNode date = XmlHelper.CreateNode(doc, "Date", "");
                    XmlHelper.SetAttribute(date, "type", "date");
                    XmlHelper.SetAttribute(date, "description", "Sample date:");

                    lastLayer = 0;
                    thickness = XmlHelper.CreateNode(doc, "Thickness", "");
                    for (int k = 0; k < sp.layers.Count; k++)
                    {
                        XmlNode dbl = XmlHelper.CreateNode(doc, "double", "");
                        int layerDepth = Int32.Parse(sp.layers[k].depth) - lastLayer;
                        lastLayer = Int32.Parse(sp.layers[k].depth);
                        XmlHelper.SetValue(dbl, "", layerDepth.ToString() + "0");
                        thickness.AppendChild(dbl);
                    }
                    initN.AppendChild(thickness);

                    XmlNode no3 = XmlHelper.CreateNode(doc, "NO3", "");
                    for (int k = 0; k < sp.layers.Count; k++)
                    {
                        XmlNode dbl = XmlHelper.CreateNode(doc, "double", "");
                        XmlHelper.SetValue(dbl, "", "0.1");
                        no3.AppendChild(dbl);
                    }
                    initN.AppendChild(no3);

                    XmlNode nh4 = XmlHelper.CreateNode(doc, "NH4", "");
                    for (int k = 0; k < sp.layers.Count; k++)
                    {
                        XmlNode dbl = XmlHelper.CreateNode(doc, "double", "");
                        XmlHelper.SetValue(dbl, "", "0.1");
                        nh4.AppendChild(dbl);
                    }
                    initN.AppendChild(nh4);

                    attr = XmlHelper.Find(soil, "SoilType");
                    XmlHelper.SetAttribute(attr, "description", "Classification");
                    attr = XmlHelper.Find(soil, "NearestTown");
                    XmlHelper.SetAttribute(attr, "description", "Nearest Town");
                    attr = XmlHelper.Find(soil, "NaturalVegetation");
                    XmlHelper.SetAttribute(attr, "description", "Natural Vegetation");
                    attr = XmlHelper.Find(soil, "ApsoilNumber");
                    XmlHelper.SetAttribute(attr, "description", "Apsoil Number");
                    attr = XmlHelper.Find(soil, "Latitude");
                    XmlHelper.SetAttribute(attr, "description", "Latitude (WGS84)");
                    attr = XmlHelper.Find(soil, "Longitude");
                    XmlHelper.SetAttribute(attr, "description", "Longitude (WGS84)");
                    attr = XmlHelper.Find(soil, "LocationAccuracy");
                    XmlHelper.SetAttribute(attr, "description", "Location Accuracy");
                    attr = XmlHelper.Find(soil, "DataSource");
                    XmlHelper.SetAttribute(attr, "type", "multiedit");
                    XmlHelper.SetAttribute(attr, "description", "DataSource");
                    attr = XmlHelper.Find(soil, "Comments");
                    XmlHelper.SetAttribute(attr, "description", "Comments");

                    soil.AppendChild(water);
                    soil.AppendChild(soilWat);
                    soil.AppendChild(soilOM);
                    soil.AppendChild(analysis);
                    soil.AppendChild(initWater);
                    soil.AppendChild(initN);
                    root.AppendChild(soil);
                }
            }
            Console.WriteLine("Writing Apsim soil file.");
            Console.ReadKey();
            var remEmpty = XDocument.Parse(doc.InnerXml);
            remEmpty.Descendants().Where(e => e.IsEmpty || String.IsNullOrWhiteSpace(e.Value)).Remove(); //deserialiser doesn't like empty nodes. Use LINQ to remove them.
            remEmpty.Save(@"C:\temp\EB2.soils");
        }