【问题标题】:Issue with formating of kml file with XDocument.Save使用 XDocument.Save 格式化 kml 文件的问题
【发布时间】:2018-02-01 07:56:52
【问题描述】:

我有一个类似这样的“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:”前缀?如何删除/格式化它们?

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

编辑: “正确的格式”是指正确的 xml 格式、颜色和其他格式,如第一张图片所示。

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

【问题讨论】:

  • 1. “正确的格式”是什么意思?
  • 问题是您的 XML 具有相同命名空间的重复命名空间前缀:xmlns="http://www.opengis.net/kml/2.2"xmlns:kml="http://www.opengis.net/kml/2.2"。而且,事实证明,在编写 XElement 时,命名空间进入下推堆栈,因此 last 重复命名空间控制使用的命名空间前缀。这就是为什么到处都添加kml: 前缀的原因。当然,两者都可以使用,并且 XML 在语义上是等效的 - 但只是看起来不同。
  • 这在XDocument duplicate namespace with different Local Name中有解释——事实上我认为这是重复的。
  • 感谢@dbc 的澄清。有没有一种简单的方法来显示/格式化它而不在任何地方添加前缀?
  • 是的,消除重复的xmlns:kml="http://www.opengis.net/kml/2.2" 命名空间。请记住,无论前缀是否存在,这只是一个表面问题,因为默认命名空间与 kml: 命名空间相同。

标签: c# xml kml


【解决方案1】:

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

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

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

2。为什么它在每个节点之前添加“kml:”作为前缀?如何删除/格式化它们?

这是因为 kmlXDocument.Save 有一个重复的命名空间,如 dbc 在 cmets 中提到的那样,将最后一个匹配的命名空间应用于每个节点。此外,这只是一个外观问题,您不必担心。

但是,您可以通过在保存之前删除 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>

【讨论】:

    【解决方案2】:

    您的问题的一部分(关于“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);
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-12-29
      • 2016-07-15
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多