Search code examples
c#xmlkml

Issue with formating of kml file with XDocument.Save


I have a "t.kml" file something like this:

<?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:atom="http://www.w3.org/2005/Atom">
<Document>
    <name>Test.kml</name>
    <Folder>
        <name>Test</name>
        <open>1</open>
        <Placemark>
            <name>Placemark 1</name>
            <LookAt>
                <longitude>-150.7482419621821</longitude>
                <latitude>72.7616508182995</latitude>
                <altitude>0</altitude>
                <heading>-13.26929942603143</heading>
                <tilt>0</tilt>
                <range>33665.16192218825</range>
                <gx:altitudeMode>relativeToSeaFloor</gx:altitudeMode>
            </LookAt>
            <styleUrl>#m_ylw-pushpin</styleUrl>
            <Point>
                <gx:drawOrder>1</gx:drawOrder>
                <coordinates>-110.7484519621821,52.7616508182995,0</coordinates>
            </Point>
        </Placemark>
    </Folder>
</Document>
</kml>

When I run this in firefox it shows like this: enter image description here

I have this simple c# code which just opens and save it (though it does lot other things).

    DialogResult result = openFileDialog2.ShowDialog();

    if (result == DialogResult.OK)
    {
        string fileName = openFileDialog2.FileName;

        var xdoc = XDocument.Load(fileName, LoadOptions.None);

        xdoc.Save("G:/Projects/t1.kml", SaveOptions.None);
    }

After saving it when I open this new file it is shown as: enter image description here

The issues are:

(1) Why it is not shown in proper format?

(2) Why does it adds "kml:" as prefix before every node? How can I remove/format them?

How do I the resolve both these issue?

Edit: By 'proper format' I mean proper xml format, the colors and other formatting as shown in first picture.

Edit 2: How do I ensure that when it runs in a browser it shows the expand/collapse icons and colors too.


Solution

  • 1. Why it is not shown in proper format?

    That's because Firefox tries to auto-detect the filetype based on extension and data. Because your file doesn't end with .xml and XDocument.Save adds a BOM to the output file, the file is not shown as XML.

    So you could save your file without BOM by using a XmlTextWriter (see this answer) or rename your file to .xml if you just want to view it occasionally with Firefox.

    2. Why does it adds "kml:" as prefix before every node? How can I remove/format them?

    That's because you have a duplicate namespace for kml and XDocument.Save applies the last matching namespace to each node as mentioned by dbc in the comments. Also, this is just a cosmetic issue you shouldn't have to worry about.

    However you can workaround this by removing the xmlns:kml namespace declaration before saving it:

    var doc = XDocument.Load(fileName, LoadOptions.None);
    foreach (var attr in doc.Root.Attributes())
        if (attr.IsNamespaceDeclaration && attr.Name.LocalName == "kml")
            attr.Remove();
    doc.Save(@"G:\Projects\t1.kml", SaveOptions.None);
    

    Outputs

    <?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:atom="http://www.w3.org/2005/Atom">
      <Document>
        <name>Test.kml</name>
        <Folder>
          <name>Test</name>
          <open>1</open>
          <Placemark>
            <name>Placemark 1</name>
            <LookAt>
              <longitude>-150.7482419621821</longitude>
              <latitude>72.7616508182995</latitude>
              <altitude>0</altitude>
              <heading>-13.26929942603143</heading>
              <tilt>0</tilt>
              <range>33665.16192218825</range>
              <gx:altitudeMode>relativeToSeaFloor</gx:altitudeMode>
            </LookAt>
            <styleUrl>#m_ylw-pushpin</styleUrl>
            <Point>
              <gx:drawOrder>1</gx:drawOrder>
              <coordinates>-110.7484519621821,52.7616508182995,0</coordinates>
            </Point>
          </Placemark>
        </Folder>
      </Document>
    </kml>