-6

I have a Datatable Cities containing the following data (only 3 out of 60000 items I am posting).

I want to create an xml(KML) from the data provided.

How to create generic solution?

Perhaps creating classes and adding properties and then loading in to xml.

This would be the XML generated.i am posting only a portion

<?xml version="1.0" encoding="UTF-8"?>
<kml xmlns="http://www.opengis.net/kml/2.2" xmlns:gx="http://www.google.com/kml/ext/2.2"
 xmlns:kml="http://www.opengis.net/kml/2.2" xmlns:json="http://www.w3.org/2005/Json">
  <Folder>
    <name>USA</name>
    <open>1</open>
    <Folder>
      <name>Corperation</name>
      <open>1</open>
      <Folder>
        <name>LARGE</name>
        <Folder>
          <name>WORKING</name>
          <Document>
            <name>POINTS</name>
            <StyleMap id="Licerio0_0">
              <Pair>
                <key>normal</key>
                <styleUrl>#Licerio0_0N</styleUrl>
              </Pair>
              <Pair>
                <key>highlight</key>
                <styleUrl>#Licerio0_0H</styleUrl>
              </Pair>
            </StyleMap>
            <Style id="Licerio0_0N">
              <IconStyle>
                <color>ff00ff00</color>
                <scale>0.4</scale>
                <Icon>
                  http://maps.google.com/mapfiles/kml/shapes/shaded_dot.png
                </Icon>
              </IconStyle>
              <LabelStyle>
                <color>ff00ff00</color>
                <scale>0.6</scale>
              </LabelStyle>
              <BalloonStyle>
                <text>$[description]</text>
              </BalloonStyle>
              <LineStyle>
                <antialias>0</antialias>
              </LineStyle>
              <PolyStyle>
                <fill>0</fill>
                <outline>0</outline>
              </PolyStyle>
            </Style>
            <Placemark>
              <name>NEWYORK</name>
              <description>
                <![CDATA[<img src="http://upload.wikimedia.org/wikipedia/commons/USA.png"width="47" height="67">
  <br>RSID = <b>NEWYORK</b><ul>
   <li>PIN = 676306
   <li>LONGITUDE = 54.4251
   <li>LATITUDE = 25.6011
   <li>SCALE = 0.7
   <li>TOTAL TILT = 4
   <li>CH = 87
   <li>REGION = NEM</ul></li>]]>
              </description>
              <styleUrl>#Licerio0_0</styleUrl>
              <Point>
                <gx:drawOrder>3</gx:drawOrder>
                <coordinates>54.4251,25.6011,0</coordinates>
              </Point>
            </Placemark>  
          </Document>

*

*<Document>
            <name>LINES</name>
            <Style id="Zamoras0_0">
            </Style>
            <Placemark>
              <name>***Site Id***</name>
              <styleUrl>#Zamoras0_0</styleUrl>
              <MultiGeometry>
                <LineString>
                  <gx:drawOrder>3</gx:drawOrder>
                  <coordinates>***LONGITUDE***,***LATITUDE***,***SCALE***</coordinates>
                </LineString>
              </MultiGeometry>
            </Placemark>
          </Document>**
        </Folder>
      </Folder>

    </Folder>
.
.
ETC.......
  </Folder>
</kml>

EDIT Small change in template,two documents are there one for LINES and another for POINTS.If i have internal streets ,then it should be added inside placemarks of both document section.i am editing my question.How to do that?if i use this code it is duplicating

dt.Columns.Add("countryname", typeof(string));
            dt.Columns.Add("citytype", typeof(string));
            dt.Columns.Add("size", typeof(string));
            dt.Columns.Add("status", typeof(string));
            dt.Columns.Add("cityname", typeof(string));
            dt.Columns.Add("pin", typeof(int));
            dt.Columns.Add("LONGITUDE", typeof(double));
            dt.Columns.Add("LATITUDE", typeof(double));
            dt.Columns.Add("SCALE", typeof(double));
            dt.Columns.Add("TOTAL", typeof(int));
            dt.Columns.Add("TILT", typeof(string));
            dt.Columns.Add("CH", typeof(string));
            dt.Columns.Add("REGION", typeof(string));
            dt.Columns.Add("streets", typeof(string));

            dt.Rows.Add(new object[] { "USA", "Corperation", "LARGE", "WORKING", "newyork", 676306, 24.4251, 25.6011, 0.0, 87, "NEM","firststreet" });
       dt.Rows.Add(new object[] { "USA", "Corperation", "LARGE", "WORKING", "newyork", 676306, 24.4251, 25.6011, 0.0, 87, "NEM","downtownstreet" });
            dt.Rows.Add(new object[] { "USA", "Corperation", "LARGE", "WORKING", "chicago", 676306, 24.4251, 25.6011, 0.0, 87, "NEM","chicstreet" });
            dt.Rows.Add(new object[] { "USA", "Corperation", "LARGE", "WORKING", "la", 676306, 24.4251, 25.6011, 0.0, 87, "NEM","lastreet" });
            dt.Rows.Add(new object[] { "USA", "Corperation", "MEDIUM", "WORKING", "buffalo", 676306, 24.4251, 25.6011, 0.0, 87, "NEM","buffalostreet" });
dt.Rows.Add(new object[] { "USA", "Corperation", "MEDIUM", "WORKING", "buffalo", 676306, 24.4251, 25.6011, 0.0, 87, "NEM","cowstreet" });
            dt.Rows.Add(new object[] { "USA", "Corperation", "MEDIUM", "WORKING", "denver", 676306, 24.4251, 25.6011, 0.0, 87, "NEM","street" });
            dt.Rows.Add(new object[] { "USA", "Corperation", "MEDIUM", "NOT WORKING", "lasvegas", 676306, 24.4251, 25.6011, 0.0, 87, "NEM","street" });
            dt.Rows.Add(new object[] { "USA", "Corperation", "SMALL", "WORKING", "trenton", 676306, 24.4251, 25.6011, 0.0, 87, "NEM" ,"street"});
            dt.Rows.Add(new object[] { "USA", "Village", "SMALL", "WORKING", "albany", 676306, 24.4251, 25.6011, 0.0, 87, "NEM","street" });
            dt.Rows.Add(new object[] { "USA", "Village", "SMALL", "WORKING", "hartford", 676306, 24.4251, 25.6011, 0.0, 87, "NEM","street" });
            dt.Rows.Add(new object[] { "SPAIN", "Corperation", "MEDIUM", "WORKING", "BARCELONA", 11111, 34.4251, 25.6011, 0.0, 82, "LEV" });
            dt.Rows.Add(new object[] { "ITALY", "Corperation", "LARGE", "WORKING", "ITALY", 21111, 14.4251, 15.6011, 0.0, 80, "MIR" });
peter
  • 8,158
  • 21
  • 66
  • 119
  • 1
    What have your tried? – CodeNotFound Aug 17 '16 at 17:59
  • 2
    can you load the data into a DataSet then using Write the results an XML file do a google search on the following `C# Stackoverflow Export DataTable to XML File` – MethodMan Aug 17 '16 at 18:00
  • 1
    DataTable comes with a [WriteToXml Method](https://msdn.microsoft.com/en-us/library/system.data.datatable.writexml(v=vs.110).aspx) ... just transform the resulting Xml using Xslt. Shouldn't be too hard. – Filburt Aug 17 '16 at 18:07
  • IT would be great,if you can post the code snippet for that, – peter Aug 17 '16 at 18:10
  • May be a duplicate, check out this thread: http://stackoverflow.com/questions/13072927/create-an-xml-from-a-datatable – hmiedema9 Aug 17 '16 at 18:47

1 Answers1

1

Before anybody gives me negative points for this highly unusual solution, please understand the problems. 1) The multiple Folder nested tags 2) The html text

I using a xml template file to read intial xml. This xml is complicated so I don't think it is wise to create the xml from scratch.

Use the following xml template for main file

<?xml version="1.0" encoding="UTF-8"?>
<kml xmlns="http://www.opengis.net/kml/2.2" xmlns:gx="http://www.google.com/kml/ext/2.2"
 xmlns:kml="http://www.opengis.net/kml/2.2" xmlns:json="http://www.w3.org/2005/Json">
  <Folder>
    <name>***COUNTRY***</name>
    <open>1</open>
    <Folder>
      <name>***CITY TYPE***</name>
      <open>1</open>
      <Folder>
        <name>***SIZE***</name>
        <Folder>
          <name>***STATUS***</name>
          <Document>
            <name>POINTS</name>
            <StyleMap id="Licerio0_0">
              <Pair>
                <key>normal</key>
                <styleUrl>#Licerio0_0N</styleUrl>
              </Pair>
              <Pair>
                <key>highlight</key>
                <styleUrl>#Licerio0_0H</styleUrl>
              </Pair>
            </StyleMap>
            <Style id="Licerio0_0N">
              <IconStyle>
                <color>ff00ff00</color>
                <scale>0.4</scale>
                <Icon>
                  http://maps.google.com/mapfiles/kml/shapes/shaded_dot.png
                </Icon>
              </IconStyle>
              <LabelStyle>
                <color>ff00ff00</color>
                <scale>0.6</scale>
              </LabelStyle>
              <BalloonStyle>
                <text>$[description]</text>
              </BalloonStyle>
              <LineStyle>
                <antialias>0</antialias>
              </LineStyle>
              <PolyStyle>
                <fill>0</fill>
                <outline>0</outline>
              </PolyStyle>
            </Style>
            <Placemark>
              <name>***CITY NAME***</name>
              <description>
                <![CDATA[<img src="http://upload.wikimedia.org/wikipedia/commons/***COUNTRY***.png"width="47" height="67">
  <br>RSID = <b>***CITY NAME***</b><ul>
   <li>PIN = ***PIN***
   <li>LONGITUDE = ***LONGITUDE***
   <li>LATITUDE = ***LATITUDE***
   <li>SCALE = ***SCALE***
   <li>TOTAL TILT = ***TILT***
   <li>CH = ***CH***
   <li>REGION = ***REGION***</ul></li>]]>
              </description>
              <styleUrl>#Licerio0_0</styleUrl>
              <Point>
                <gx:drawOrder>3</gx:drawOrder>
                <coordinates>***LONGITUDE***,***LATITUDE***,***SCALE***</coordinates>
              </Point>
            </Placemark>
          </Document>
        </Folder>
      </Folder>

    </Folder>
  </Folder>
</kml>

The use following template for 2nd file

<?xml version="1.0" encoding="utf-8" ?>
<kml xmlns="http://www.opengis.net/kml/2.2" xmlns:gx="http://www.google.com/kml/ext/2.2"
 xmlns:kml="http://www.opengis.net/kml/2.2" xmlns:json="http://www.w3.org/2005/Json">
  <name>LINES</name>
  <Style id="Zamoras0_0">
  </Style>
  <Placemark>
    <name>***Site Id***</name>
    <styleUrl>#Zamoras0_0</styleUrl>
    <MultiGeometry>
      <LineString>
        <gx:drawOrder>3</gx:drawOrder>
        <coordinates>***LONGITUDE***,***LATITUDE***,***SCALE***</coordinates>
      </LineString>
    </MultiGeometry>
  </Placemark>
</kml>

Then use code below

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.Xml;
using System.Xml.Linq;

namespace ConsoleApplication9
{
    class Program
    {
        const string FILENAME1 = @"c:\temp\test1.xml";
        const string FILENAME2 = @"c:\temp\test2.xml";
        static void Main(string[] args)
        {
            DataTable dt = new DataTable();
            dt.Columns.Add("countryname", typeof(string));
            dt.Columns.Add("citytype", typeof(string));
            dt.Columns.Add("size", typeof(string));
            dt.Columns.Add("status", typeof(string));
            dt.Columns.Add("cityname", typeof(string));
            dt.Columns.Add("pin", typeof(int));
            dt.Columns.Add("LONGITUDE", typeof(double));
            dt.Columns.Add("LATITUDE", typeof(double));
            dt.Columns.Add("SCALE", typeof(double));
            dt.Columns.Add("TOTAL", typeof(int));
            dt.Columns.Add("TILT", typeof(string));
            dt.Columns.Add("CH", typeof(string));
            dt.Columns.Add("REGION", typeof(string));
            dt.Columns.Add("streets", typeof(string));

            dt.Rows.Add(new object[] { "USA", "Corperation", "LARGE", "WORKING", "newyork", 676306, 24.4251, 25.6011, 0.0, 87, "NEM", "", "", "firststreet" });
            dt.Rows.Add(new object[] { "USA", "Corperation", "LARGE", "WORKING", "newyork", 676306, 24.4251, 25.6011, 0.0, 87, "NEM", "", "", "downtownstreet" });
            dt.Rows.Add(new object[] { "USA", "Corperation", "LARGE", "WORKING", "chicago", 676306, 24.4251, 25.6011, 0.0, 87, "NEM", "", "", "chicstreet" });
            dt.Rows.Add(new object[] { "USA", "Corperation", "LARGE", "WORKING", "la", 676306, 24.4251, 25.6011, 0.0, 87, "NEM", "", "", "lastreet" });
            dt.Rows.Add(new object[] { "USA", "Corperation", "MEDIUM", "WORKING", "buffalo", 676306, 24.4251, 25.6011, 0.0, 87, "NEM", "", "", "buffalostreet" });
            dt.Rows.Add(new object[] { "USA", "Corperation", "MEDIUM", "WORKING", "buffalo", 676306, 24.4251, 25.6011, 0.0, 87, "NEM", "", "", "cowstreet" });
            dt.Rows.Add(new object[] { "USA", "Corperation", "MEDIUM", "WORKING", "denver", 676306, 24.4251, 25.6011, 0.0, 87, "NEM", "", "", "street" });
            dt.Rows.Add(new object[] { "USA", "Corperation", "MEDIUM", "NOT WORKING", "lasvegas", 676306, 24.4251, 25.6011, 0.0, 87, "NEM", "", "", "street" });
            dt.Rows.Add(new object[] { "USA", "Corperation", "SMALL", "WORKING", "trenton", 676306, 24.4251, 25.6011, 0.0, 87, "NEM", "", "", "street" });
            dt.Rows.Add(new object[] { "USA", "Village", "SMALL", "WORKING", "albany", 676306, 24.4251, 25.6011, 0.0, 87, "NEM", "", "", "street" });
            dt.Rows.Add(new object[] { "USA", "Village", "SMALL", "WORKING", "hartford", 676306, 24.4251, 25.6011, 0.0, 87, "NEM", "", "", "street" });
            dt.Rows.Add(new object[] { "SPAIN", "Corperation", "MEDIUM", "WORKING", "BARCELONA", 11111, 34.4251, 25.6011, 0.0, 82, "LEV" });
            dt.Rows.Add(new object[] { "ITALY", "Corperation", "LARGE", "WORKING", "ITALY", 21111, 14.4251, 15.6011, 0.0, 80, "MIR" });

            XDocument doc1 = XDocument.Load(FILENAME1);
            XElement kml = (XElement)doc1.FirstNode;
            XNamespace ns = kml.Name.Namespace;
            XElement document = doc1.Descendants().Where(x => x.Name.LocalName == "Document").FirstOrDefault();
            string documentStr = document.ToString();
            kml.RemoveAll();

            XDocument doc2 = XDocument.Load(FILENAME2);
            XElement linesDoc = (XElement)doc2.FirstNode;
            string linesStr = linesDoc.ToString();


            var countryRows = dt.AsEnumerable().GroupBy(x => x.Field<string>("countryname"));
            foreach (var country in countryRows)
            {
                XElement newCountry = new XElement(ns + "Folder", new object[] {
                       new XElement(ns + "name", country.Key),
                       new XElement(ns + "open", 1)
                });
                kml.Add(newCountry);

                var cityTypeRows = country.GroupBy(x => x.Field<string>("citytype"));
                foreach (var cityTypeRow in cityTypeRows)
                {
                    XElement newCityType = new XElement(ns + "Folder", new object[] {
                       new XElement(ns + "name", cityTypeRow.Key),
                       new XElement(ns + "open", 1)
                    });
                    newCountry.Add(newCityType);

                    var citySizeRows = cityTypeRow.GroupBy(x => x.Field<string>("size"));
                    foreach (var citySizeRow in citySizeRows)
                    {
                        XElement newCitySize = new XElement(ns + "Folder", new object[] {
                           new XElement(ns + "name", citySizeRow.Key)
                        });
                        newCityType.Add(newCitySize);

                        var cityStatusRows = cityTypeRow.GroupBy(x => x.Field<string>("status"));
                        foreach (var cityStatusRow in cityStatusRows)
                        {
                            XElement newStatus = new XElement(ns + "Folder", new object[] {
                               new XElement(ns + "name", cityStatusRow.Key)
                            });
                            newCitySize.Add(newStatus);

                            var cityRows = cityTypeRow.GroupBy(x => x.Field<string>("cityname"));
                            foreach (var city in cityRows)
                            {

                                string newDocumentStr = documentStr;
                                newDocumentStr = newDocumentStr.Replace("***CITY NAME***", city.Key);
                                newDocumentStr = newDocumentStr.Replace("***PIN***", city.FirstOrDefault().Field<int>("pin").ToString());
                                newDocumentStr = newDocumentStr.Replace("***LONGITUDE***", city.FirstOrDefault().Field<double>("LONGITUDE").ToString());
                                newDocumentStr = newDocumentStr.Replace("***LATITUDE***", city.FirstOrDefault().Field<double>("LATITUDE").ToString());
                                newDocumentStr = newDocumentStr.Replace("***SCALE***", city.FirstOrDefault().Field<double>("SCALE").ToString());
                                newDocumentStr = newDocumentStr.Replace("***TOTAL***", city.FirstOrDefault().Field<int>("TOTAL").ToString());
                                newDocumentStr = newDocumentStr.Replace("***TILT***", city.FirstOrDefault().Field<string>("TILT"));
                                newDocumentStr = newDocumentStr.Replace("***CH***", city.FirstOrDefault().Field<string>("CH"));
                                newDocumentStr = newDocumentStr.Replace("***REGION***", city.FirstOrDefault().Field<string>("REGION"));

                                XElement newCity = XElement.Parse(newDocumentStr);
                                newCitySize.Add(newCity);
                                foreach (var street in city)
                                {
                                    if (street.Field<object>("streets") != null)
                                    {
                                        string newlinesStr = linesStr;
                                        newlinesStr = newlinesStr.Replace("***LONGITUDE***", street.Field<double>("LONGITUDE").ToString());
                                        newlinesStr = newlinesStr.Replace("***LATITUDE***", street.Field<double>("LATITUDE").ToString());
                                        newlinesStr = newlinesStr.Replace("***SCALE***", street.Field<double>("SCALE").ToString());
                                        newlinesStr = newlinesStr.Replace("***Site Id***", street.Field<string>("streets").ToString());

                                        XElement newLine = XElement.Parse(newlinesStr);
                                        newCity.Add(newLine.Elements());
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
jdweng
  • 33,250
  • 2
  • 15
  • 20
  • This looks a good concept,let me see it – peter Aug 19 '16 at 04:07
  • 1
    I added output xml file to answer. – jdweng Aug 19 '16 at 11:54
  • 1
    I updated code to create separate folders. – jdweng Aug 20 '16 at 15:22
  • Small change in template,two documents are there one for LINES and another for POINTS.If i have internal city points ,then it should be added inside placemarks of both document section.i am editing my question.How to do that?if i use this code it is duplicating – peter Aug 20 '16 at 18:03
  • I think I got it correct. – jdweng Aug 21 '16 at 00:30
  • This was a protoype,i dont know what went wrong ,There should be two document for same sountry having same type and statuses,only Placemark is appened?The real question i posted in http://stackoverflow.com/questions/39059704/how-to-create-xml-from-xml-template-in-c-sharp – peter Aug 21 '16 at 02:05
  • The code I posted works with the xml I supplied. The other posting doesn't have the streets so I'm not sure why I should go backwards. Work with current code. The columns in your datatable and data are missing columns. The xml you posted is missing the gx prefix. I fixed all these issues. I'm also using two xml input files. – jdweng Aug 21 '16 at 10:39
  • i know it is late,but i want to know How to uncheck folders in KML file while initial loading..i have made visibility to 0 but no luck at all,still loading all data when i load with Google Earth .How to uncheck all folders and inside items so user can select which ever required in later – peter Feb 21 '17 at 02:19
  • I would load everything then put items into a TreeView with check items. Then uncheck items not wanted. http://stackoverflow.com/questions/5478984/treeview-with-checkboxes-in-c-sharp and http://stackoverflow.com/questions/28976601/recursion-parsing-xml-file-with-attributes-into-treeview-c-sharp – jdweng Feb 21 '17 at 08:08
  • i think you misunderstood my question.I dont want to show in .net application rather Google Earth only.So i need a KML with uncheck items – peter Feb 21 '17 at 15:42
  • How and where do you want to filter? – jdweng Feb 21 '17 at 16:52
  • here above template CITY TYPE on wards everything should be unchecked .So when he selects any of the parent nodes later corresponding child should be cheked – peter Feb 21 '17 at 21:29
  • There are no checkboxes, Right? So what control do you want use for the checkboxes? – jdweng Feb 21 '17 at 22:20
  • check box i am talking about the one in Googel Earth tool.Right now huge data is loaded.But i heard like there are Visibility tag which if you set it will not load all the data at initial stage and later we can select which ever nodes required.see the question in http://stackoverflow.com/questions/42353749/how-to-uncheck-folders-in-kml-file – peter Feb 22 '17 at 21:00
  • Document has an open property and since you didn't specify the open it defaults to 1 and all the parents are opened. – jdweng Feb 22 '17 at 21:51
  • thanks i will try it, but thats for Opening not for unchecking the check boxes??? – peter Feb 24 '17 at 14:37
  • Aren't the check boxes on a Webpage? So can't user just uncheck? I think you should be able to control the webpage though Net Library code – jdweng Feb 24 '17 at 17:43