【问题标题】:XDocument: saving XML to file without BOMXDocument:将 XML 保存到没有 BOM 的文件
【发布时间】:2011-06-23 23:46:55
【问题描述】:

我正在使用 XDocument 生成一个 utf-8 XML 文件。

XDocument xml_document = new XDocument(
                    new XDeclaration("1.0", "utf-8", null),
                    new XElement(ROOT_NAME,                    
                    new XAttribute("note", note)
                )
            );
...
xml_document.Save(@file_path);

文件已正确生成并使用 xsd 文件验证成功。

当我尝试将 XML 文件上传到在线服务时,该服务说我的文件是 wrong at line 1;我发现问题是由文件第一个字节上的 BOM 引起的。

您知道为什么将 BOM 附加到文件中吗?没有它我如何保存文件?

Byte order mark维基百科文章所述:

虽然 Unicode 标准允许 BOM 在 UTF-8 不需要或 推荐它。字节顺序没有 在 UTF-8 中的含义,所以只有 BOM 用于识别文本流或 文件为 UTF-8 或已转换 来自具有 BOM 的另一种格式

这是XDocument 的问题还是我应该联系在线服务提供商的人要求解析器升级?

【问题讨论】:

    标签: c# linq-to-xml byte-order-mark


    【解决方案1】:

    使用 XmlTextWriter 并将其传递给 XDocument 的 Save() 方法,这样您就可以更好地控制所使用的编码类型:

    var doc = new XDocument(
        new XDeclaration("1.0", "utf-8", null),
        new XElement("root", new XAttribute("note", "boogers"))
    );
    using (var writer = new XmlTextWriter(".\\boogers.xml", new UTF8Encoding(false)))
    {
        doc.Save(writer);
    }
    

    UTF8Encoding 类构造函数有一个重载,它指定是否使用带有布尔值的 BOM(字节顺序标记),在您的情况下为 false

    此代码的结果已使用 Notepad++ 检查文件的编码进行验证。

    【讨论】:

    • 当您使用 Notepad++ 打开它时,即使使用new UTF8Encoding(false),它仍然是 utf-8 格式吗?
    • 我以为你想要它在 UTF-8 中,只是没有 BOM?
    • 是的,没错。我只是在问new UTF8Encoding(false) 是否还有其他含义。
    • 考虑添加writer.Formatting = Formatting.Indented;
    • 警告: Dercsár 的解决方案更好。 “从 .NET Framework 2.0 开始,我们建议您使用 XmlWriter.Create 方法和 XmlWriterSettings 类创建 XmlWriter 实例,以利用新功能。”。来源:XmlTextWriter Constructor (String, Encoding) (System.Xml)
    【解决方案2】:

    首先:服务提供商必须根据 XML 规范处理它,该规范规定 BOM 可能存在于 UTF-8 表示的情况下。

    您可以像这样强制保存没有 BOM 的 XML:

    XmlWriterSettings settings = new XmlWriterSettings();
    settings.Encoding = new UTF8Encoding(false); // The false means, do not emit the BOM.
    using (XmlWriter w = XmlWriter.Create("my.xml", settings))
    {
        doc.Save(w);
    }
    

    (从这里谷歌搜索:http://social.msdn.microsoft.com/Forums/en/xmlandnetfx/thread/ccc08c65-01d7-43c6-adf3-1fc70fdb026a

    【讨论】:

    • 在 UTF-8 表示的情况下可能存在 BOM 你能指出那个具体的文件吗?
    • 给你:w3.org/TR/2006/REC-xml-20060816/#charencoding 第一段:“所有 XML 处理器必须能够读取 UTF-8 和 UTF-16 编码的实体。” UTF-8 编码启用(虽然不是必需的)BOM(请参阅下面 Joe 的评论),因此 XML 处理器必须能够处理带有 BOM 的 UTF-8 文件。
    • "虽然 Unicode 标准允许在 UTF-8 中使用 BOM,但它不需要也不推荐使用它。字节顺序在 UTF-8 中没有意义" - en.wikipedia.org/wiki/Byte_order_mark
    • 警告:这样做而不只是 doc.Save(filename) 有一个副作用:所有内容都写在一行上。如果您希望文件保持可读性,请考虑在此答案的代码中添加 settings.Indent = true;
    【解决方案3】:

    使用 XDocument 时摆脱 BOM 字符的最便捷方法是保存文档,然后直接将文件读取为文件,然后将其写回。 File 例程会为您删除字符:

            XDocument xTasks = new XDocument();
            XElement xRoot = new XElement("tasklist",
                new XAttribute("timestamp",lastUpdated),
                new XElement("lasttask",lastTask)
            );
            ...
            xTasks.Add(xRoot);
            xTasks.Save("tasks.xml");
    
            // read it straight in, write it straight back out. Done.
            string[] lines = File.ReadAllLines("tasks.xml");
            File.WriteAllLines("tasks.xml",lines);
    

    (这很不错,但它是为了方便起见 - 至少您将有一个格式良好的文件上传到您的在线提供商);)

    【讨论】:

    • 只需使用XmlWriter.CreateXmlWriterSettings.Indent = true;。在这里,您可以按照您认为合适的方式格式化输出。
    【解决方案4】:

    通过 UTF-8 文档

    String XMLDec = xDoc.Declaration.ToString();
    StringBuilder sb = new StringBuilder(XMLDec);
    sb.Append(xDoc.ToString());
    Encoding encoding = new UTF8Encoding(false); // false = without BOM
    File.WriteAllText(outPath, sb.ToString(), encoding); 
    

    【讨论】:

    • 正如已经多次回答的那样,它也很模糊,为什么您在这里使用 StringBuilder 而文档可以保存自己,如其他答案所示。解释一下。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-28
    • 1970-01-01
    • 2016-05-07
    • 1970-01-01
    • 2011-09-21
    相关资源
    最近更新 更多