XDocument.Save 的 kml 文件格式问题

Issue with formating of kml file with XDocument.Save

我有一个 "t.kml" 文件是这样的:

<?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>

当我在 firefox 中 运行 时,它显示如下:

我有这个简单的 C# 代码,它只是打开并保存它(尽管它还做了很多其他事情)。

    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);
    }

打开这个新文件保存后显示为:

问题是:

(1) 为什么显示格式不正确?

(2) 为什么在每个节点前都加"kml:"作为前缀?我怎样才能 remove/format 他们?

我该如何解决这两个问题?

编辑: 'proper format' 我的意思是正确的 xml 格式、颜色和其他格式如第一张图片所示。

编辑 2: 我如何确保它在浏览器中 运行 时也显示 expand/collapse 图标和颜色。

1.为什么没有以正确的格式显示?

那是因为 Firefox 会尝试根据扩展名和数据自动检测文件类型。由于您的文件未以 .xml 结尾,并且 XDocument.Save 向输出文件添加了 BOM,因此文件未显示为 XML.

因此,您可以使用 XmlTextWriter(请参阅 )保存没有 BOM 的文件,或者如果您只是想偶尔使用 Firefox 查看文件,则将文件重命名为 .xml

2。为什么它在每个节点前添加 "kml:" 作为前缀?我怎样才能remove/format他们?

那是因为 kml 有一个重复的命名空间,而 XDocument.Save 将最后一个匹配的命名空间应用到每个节点,正如 dbc 在评论中提到的那样。此外,这只是一个您不必担心的表面问题。

不过,您可以通过在保存之前删除 xmlns:kml 命名空间声明来解决此问题:

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);

输出

<?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>

你问题的一部分(关于"kml"前缀)已经回答了,所以我只回答另一部分(关于在firefox中显示)。它在 firefox(或 chrome)中不显示为 xml 树的原因是在使用 utf-8 声明保存 XDocument 时 - 使用带有 BOM(字节顺序标记)的 UTF8。 BOM 是文件开头的 3 个特殊字节,提示文件以 UTF-8 编码。由于某些原因,这些字节混淆了 firefox,并将文件视为纯文本。

因此,要解决此问题,您需要将文档保存为不带 BOM 的 UTF-8,例如:

var xdoc = XDocument.Load(fileName, LoadOptions.None);
using (var writer = new XmlTextWriter(outputFile, new UTF8Encoding(false))) {
    xdoc.Save(writer);
}