dotnet / dotnet/dotnet-api-docs

Document that XmlDocument.Save() creates UTF-8 files *with BOM* if there's an explicit "UTF-8" encoding attribute

Open
#2,014 1 comment 0 reactions 0 assignees View on GitHub
area-System.Xml Pri3 untriaged
Dominant language
C#
Stars
949
Forks
1.7k
Avg merge
3d 27m
Merged PRs (30d)
49

Description

https://github.com/dotnet/corefx/issues/34118 demonstrates that while `XmlDocument.Save(string)` creates _BOM-less_ UTF-8 files in the _absence_ of an `encoding` attribute, signaling UTF-8 encoding _explicitly_ via an `encoding` attribute in the XML declaration unexpectedly creates a UTF-8 file _with BOM_.

This is **problematic** for two reasons:

* From a cross-platform perspective: A document with a UTF-8 (pseudo-)BOM (Unicode signature) can cause problems in cross-platform use, because many utilities on Unix-like platforms and, e.g., Java's standard libraries, where many utilities neither expect nor know how to handle such a BOM.
* While the XML standard _does_ mandate that a compliant parser must recognize a UTF-8 BOM, the reality is that XML files are often read as plain-text files.

* From an internal-consistency perspective: UTF-8 files should be created _without BOM_, as has been the default since the inception of .NET; specifying UTF-8 explicitly should only produce a BOM _if explicitly requested_ (although the standard does allow such BOMs).
* As an aside: a related intra-.NET inconsistency is that `System.Text.Encoding.UTF8` returns an encoding that _does_ produce a BOM, but this unexpected behavior is at least [documented](https://docs.microsoft.com/en-us/dotnet/api/system.text.encoding.utf8?view=netframework-4.7.2#remarks).

@krwq feels that fixing this inconsistency is too much of a breaking change, so the **behavior should be documented**; **to summarize**:

When the [`XmlDocument.Save(string)`](https://docs.microsoft.com/en-us/dotnet/api/system.xml.xmldocument.save?view=netcore-2.2#System_Xml_XmlDocument_Save_System_String_) overload is used:

* In the _absence_ of an `encoding` attribute, the `.Save(string)` method creates a UTF-8 _without BOM_, in line with .NET's default and suitable for cross-platform use.

* If a `UTF-8`-valued `encoding` attribute is present, the `.Save(string)` method creates a UTF-8-encoded file _with BOM_.

* Note that it doesn't matter whether a given document was originally read from a _file_ / a _string_ with an explicit `encoding="UTF-8"` attribute (the case of `UTF-8` doesn't matter) in its XML declaration, or whether a UTF-8 `encoding` attribute was created _programmatically_ via `XmlDocument.CreateXmlDeclaration()`.

* @krwq demonstrates a **workaround** based on explicit creation of an `XmlWriter` instance [here](https://github.com/dotnet/corefx/issues/34118#issuecomment-454193681).

Finally, it's also worth mentioning that using an `encoding` value that isn't recognized (as one of the default / registered .NET encodings) causes an _exception_ on calling `.Save()` (but not on _reading_).

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.