dotnet / dotnet/dotnet-api-docs
Document that XmlDocument.Save() creates UTF-8 files *with BOM* if there's an explicit "UTF-8" encoding attribute
- 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
Assessment
This issue has not been assessed yet.