From 1355936e0659ea7a96d50f000b684a7665298128 Mon Sep 17 00:00:00 2001 From: devsko Date: Wed, 8 Feb 2023 12:53:29 +0100 Subject: [PATCH 1/2] XmlWriter respects NewLineOnAttributes when writing xmlns --- .../src/System.Private.Xml.csproj | 9 ++--- .../Xml/Core/XmlEncodedRawTextWriter.cs | 21 +++++++++-- .../Xml/Core/XmlEncodedRawTextWriterAsync.cs | 22 ++++++++++-- .../Core/XmlRawTextWriterGenerator.ttinclude | 21 +++++++++-- .../XmlRawTextWriterGeneratorAsync.ttinclude | 22 ++++++++++-- .../System/Xml/Core/XmlUtf8RawTextWriter.cs | 21 +++++++++-- .../Xml/Core/XmlUtf8RawTextWriterAsync.cs | 22 ++++++++++-- .../tests/System.Private.Xml.Tests.csproj | 3 +- .../tests/XmlWriter/WriteWithXmlnsNewLine.cs | 35 +++++++++++++++++++ 9 files changed, 159 insertions(+), 17 deletions(-) create mode 100644 src/libraries/System.Private.Xml/tests/XmlWriter/WriteWithXmlnsNewLine.cs diff --git a/src/libraries/System.Private.Xml/src/System.Private.Xml.csproj b/src/libraries/System.Private.Xml/src/System.Private.Xml.csproj index 2bbb69bb379cd..68e195a00847e 100644 --- a/src/libraries/System.Private.Xml/src/System.Private.Xml.csproj +++ b/src/libraries/System.Private.Xml/src/System.Private.Xml.csproj @@ -759,10 +759,7 @@ - + @@ -788,4 +785,8 @@ + + + + diff --git a/src/libraries/System.Private.Xml/src/System/Xml/Core/XmlEncodedRawTextWriter.cs b/src/libraries/System.Private.Xml/src/System/Xml/Core/XmlEncodedRawTextWriter.cs index 0f69ef093c0f8..508a8fa50abbe 100644 --- a/src/libraries/System.Private.Xml/src/System/Xml/Core/XmlEncodedRawTextWriter.cs +++ b/src/libraries/System.Private.Xml/src/System/Xml/Core/XmlEncodedRawTextWriter.cs @@ -430,13 +430,18 @@ internal override void WriteStartNamespaceDeclaration(string prefix) if (_trackTextContent && _inTextContent) { ChangeTextContentMark(false); } + if (_attrEndPos == _bufPos) + { + _bufChars[_bufPos++] = (char)' '; + } + if (prefix.Length == 0) { - RawText(" xmlns=\""); + RawText("xmlns=\""); } else { - RawText(" xmlns:"); + RawText("xmlns:"); RawText(prefix); _bufChars[_bufPos++] = (char)'='; _bufChars[_bufPos++] = (char)'"'; @@ -2037,6 +2042,18 @@ public override void WriteStartAttribute(string? prefix, string localName, strin base.WriteStartAttribute(prefix, localName, ns); } + // Same as base class, plus possible indentation. + internal override void WriteStartNamespaceDeclaration(string prefix) + { + // Add indentation + if (_newLineOnAttributes) + { + WriteIndent(); + } + + base.WriteStartNamespaceDeclaration(prefix); + } + public override void WriteCData(string? text) { _mixedContent = true; diff --git a/src/libraries/System.Private.Xml/src/System/Xml/Core/XmlEncodedRawTextWriterAsync.cs b/src/libraries/System.Private.Xml/src/System/Xml/Core/XmlEncodedRawTextWriterAsync.cs index f622c159d9f97..6ca97ede3105e 100644 --- a/src/libraries/System.Private.Xml/src/System/Xml/Core/XmlEncodedRawTextWriterAsync.cs +++ b/src/libraries/System.Private.Xml/src/System/Xml/Core/XmlEncodedRawTextWriterAsync.cs @@ -318,13 +318,18 @@ internal override async Task WriteStartNamespaceDeclarationAsync(string prefix) if (_trackTextContent && _inTextContent) { ChangeTextContentMark(false); } + if (_attrEndPos == _bufPos) + { + _bufChars[_bufPos++] = (char)' '; + } + if (prefix.Length == 0) { - await RawTextAsync(" xmlns=\"").ConfigureAwait(false); + await RawTextAsync("xmlns=\"").ConfigureAwait(false); } else { - await RawTextAsync(" xmlns:").ConfigureAwait(false); + await RawTextAsync("xmlns:").ConfigureAwait(false); await RawTextAsync(prefix).ConfigureAwait(false); _bufChars[_bufPos++] = (char)'='; _bufChars[_bufPos++] = (char)'"'; @@ -1976,6 +1981,19 @@ protected internal override async Task WriteStartAttributeAsync(string? prefix, await base.WriteStartAttributeAsync(prefix, localName, ns).ConfigureAwait(false); } + // Same as base class, plus possible indentation. + internal override async Task WriteStartNamespaceDeclarationAsync(string prefix) + { + CheckAsyncCall(); + // Add indentation + if (_newLineOnAttributes) + { + await WriteIndentAsync().ConfigureAwait(false); + } + + await base.WriteStartNamespaceDeclarationAsync(prefix).ConfigureAwait(false); + } + public override Task WriteCDataAsync(string? text) { CheckAsyncCall(); diff --git a/src/libraries/System.Private.Xml/src/System/Xml/Core/XmlRawTextWriterGenerator.ttinclude b/src/libraries/System.Private.Xml/src/System/Xml/Core/XmlRawTextWriterGenerator.ttinclude index e79b7ff1f00c2..61d85043919b0 100644 --- a/src/libraries/System.Private.Xml/src/System/Xml/Core/XmlRawTextWriterGenerator.ttinclude +++ b/src/libraries/System.Private.Xml/src/System/Xml/Core/XmlRawTextWriterGenerator.ttinclude @@ -458,13 +458,18 @@ namespace System.Xml #><#= SetTextContentMark(3, false) #> + if (_attrEndPos == _bufPos) + { + <#= BufferName #>[_bufPos++] = (<#= BufferType #>)' '; + } + if (prefix.Length == 0) { - RawText(" xmlns=\""); + RawText("xmlns=\""); } else { - RawText(" xmlns:"); + RawText("xmlns:"); RawText(prefix); <#= BufferName #>[_bufPos++] = (<#= BufferType #>)'='; <#= BufferName #>[_bufPos++] = (<#= BufferType #>)'"'; @@ -2090,6 +2095,18 @@ namespace System.Xml base.WriteStartAttribute(prefix, localName, ns); } + // Same as base class, plus possible indentation. + internal override void WriteStartNamespaceDeclaration(string prefix) + { + // Add indentation + if (_newLineOnAttributes) + { + WriteIndent(); + } + + base.WriteStartNamespaceDeclaration(prefix); + } + public override void WriteCData(string text) { _mixedContent = true; diff --git a/src/libraries/System.Private.Xml/src/System/Xml/Core/XmlRawTextWriterGeneratorAsync.ttinclude b/src/libraries/System.Private.Xml/src/System/Xml/Core/XmlRawTextWriterGeneratorAsync.ttinclude index f12e1e53cb77f..638ee0f401e67 100644 --- a/src/libraries/System.Private.Xml/src/System/Xml/Core/XmlRawTextWriterGeneratorAsync.ttinclude +++ b/src/libraries/System.Private.Xml/src/System/Xml/Core/XmlRawTextWriterGeneratorAsync.ttinclude @@ -321,13 +321,18 @@ namespace System.Xml #><#= SetTextContentMark(3, false) #> + if (_attrEndPos == _bufPos) + { + <#= BufferName #>[_bufPos++] = (<#= BufferType #>)' '; + } + if (prefix.Length == 0) { - await RawTextAsync(" xmlns=\"").ConfigureAwait(false); + await RawTextAsync("xmlns=\"").ConfigureAwait(false); } else { - await RawTextAsync(" xmlns:").ConfigureAwait(false); + await RawTextAsync("xmlns:").ConfigureAwait(false); await RawTextAsync(prefix).ConfigureAwait(false); <#= BufferName #>[_bufPos++] = (<#= BufferType #>)'='; <#= BufferName #>[_bufPos++] = (<#= BufferType #>)'"'; @@ -1919,6 +1924,19 @@ namespace System.Xml await base.WriteStartAttributeAsync(prefix, localName, ns).ConfigureAwait(false); } + // Same as base class, plus possible indentation. + internal override async Task WriteStartNamespaceDeclarationAsync(string prefix) + { + CheckAsyncCall(); + // Add indentation + if (_newLineOnAttributes) + { + await WriteIndentAsync().ConfigureAwait(false); + } + + await base.WriteStartNamespaceDeclarationAsync(prefix).ConfigureAwait(false); + } + public override Task WriteCDataAsync(string text) { CheckAsyncCall(); diff --git a/src/libraries/System.Private.Xml/src/System/Xml/Core/XmlUtf8RawTextWriter.cs b/src/libraries/System.Private.Xml/src/System/Xml/Core/XmlUtf8RawTextWriter.cs index b97fb5f2742dd..6f5ada6cab1f9 100644 --- a/src/libraries/System.Private.Xml/src/System/Xml/Core/XmlUtf8RawTextWriter.cs +++ b/src/libraries/System.Private.Xml/src/System/Xml/Core/XmlUtf8RawTextWriter.cs @@ -363,13 +363,18 @@ internal override void WriteStartNamespaceDeclaration(string prefix) { Debug.Assert(prefix != null); + if (_attrEndPos == _bufPos) + { + _bufBytes[_bufPos++] = (byte)' '; + } + if (prefix.Length == 0) { - RawText(" xmlns=\""); + RawText("xmlns=\""); } else { - RawText(" xmlns:"); + RawText("xmlns:"); RawText(prefix); _bufBytes[_bufPos++] = (byte)'='; _bufBytes[_bufPos++] = (byte)'"'; @@ -1894,6 +1899,18 @@ public override void WriteStartAttribute(string? prefix, string localName, strin base.WriteStartAttribute(prefix, localName, ns); } + // Same as base class, plus possible indentation. + internal override void WriteStartNamespaceDeclaration(string prefix) + { + // Add indentation + if (_newLineOnAttributes) + { + WriteIndent(); + } + + base.WriteStartNamespaceDeclaration(prefix); + } + public override void WriteCData(string? text) { _mixedContent = true; diff --git a/src/libraries/System.Private.Xml/src/System/Xml/Core/XmlUtf8RawTextWriterAsync.cs b/src/libraries/System.Private.Xml/src/System/Xml/Core/XmlUtf8RawTextWriterAsync.cs index 84e3cc4fa7bcd..09d68c92ecb9a 100644 --- a/src/libraries/System.Private.Xml/src/System/Xml/Core/XmlUtf8RawTextWriterAsync.cs +++ b/src/libraries/System.Private.Xml/src/System/Xml/Core/XmlUtf8RawTextWriterAsync.cs @@ -282,13 +282,18 @@ internal override async Task WriteStartNamespaceDeclarationAsync(string prefix) CheckAsyncCall(); Debug.Assert(prefix != null); + if (_attrEndPos == _bufPos) + { + _bufBytes[_bufPos++] = (byte)' '; + } + if (prefix.Length == 0) { - await RawTextAsync(" xmlns=\"").ConfigureAwait(false); + await RawTextAsync("xmlns=\"").ConfigureAwait(false); } else { - await RawTextAsync(" xmlns:").ConfigureAwait(false); + await RawTextAsync("xmlns:").ConfigureAwait(false); await RawTextAsync(prefix).ConfigureAwait(false); _bufBytes[_bufPos++] = (byte)'='; _bufBytes[_bufPos++] = (byte)'"'; @@ -1841,6 +1846,19 @@ protected internal override async Task WriteStartAttributeAsync(string? prefix, await base.WriteStartAttributeAsync(prefix, localName, ns).ConfigureAwait(false); } + // Same as base class, plus possible indentation. + internal override async Task WriteStartNamespaceDeclarationAsync(string prefix) + { + CheckAsyncCall(); + // Add indentation + if (_newLineOnAttributes) + { + await WriteIndentAsync().ConfigureAwait(false); + } + + await base.WriteStartNamespaceDeclarationAsync(prefix).ConfigureAwait(false); + } + public override Task WriteCDataAsync(string? text) { CheckAsyncCall(); diff --git a/src/libraries/System.Private.Xml/tests/System.Private.Xml.Tests.csproj b/src/libraries/System.Private.Xml/tests/System.Private.Xml.Tests.csproj index f0765630d8d63..d349b820a32b8 100644 --- a/src/libraries/System.Private.Xml/tests/System.Private.Xml.Tests.csproj +++ b/src/libraries/System.Private.Xml/tests/System.Private.Xml.Tests.csproj @@ -254,7 +254,6 @@ - PreserveNewest @@ -326,6 +325,7 @@ + @@ -437,6 +437,7 @@ + diff --git a/src/libraries/System.Private.Xml/tests/XmlWriter/WriteWithXmlnsNewLine.cs b/src/libraries/System.Private.Xml/tests/XmlWriter/WriteWithXmlnsNewLine.cs new file mode 100644 index 0000000000000..cd18ebb741164 --- /dev/null +++ b/src/libraries/System.Private.Xml/tests/XmlWriter/WriteWithXmlnsNewLine.cs @@ -0,0 +1,35 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Xunit; + +namespace System.Xml.XmlWriterTests +{ + public class XmlWriterTests_XmlnsNewLine + { + [Fact] + public static void WriteWithXmlnsNewLine() + { + XmlDocument xml = new(); + xml.LoadXml(""); + + XmlWriterSettings settings = new(); + settings.NewLineOnAttributes = true; + settings.NewLineChars = "\n"; + settings.Indent = true; + settings.IndentChars = " "; + + StringBuilder output = new(); + using (XmlWriter writer = XmlWriter.Create(output, settings)) + { + xml.Save(writer); + } + + Assert.Equal("\n\n \n", output.ToString()); + } + } +} From 124b9aefd436552911872e0ac82cec3dd7f51aef Mon Sep 17 00:00:00 2001 From: devsko Date: Wed, 8 Feb 2023 13:02:44 +0100 Subject: [PATCH 2/2] formatting --- .../System.Private.Xml/src/System.Private.Xml.csproj | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/libraries/System.Private.Xml/src/System.Private.Xml.csproj b/src/libraries/System.Private.Xml/src/System.Private.Xml.csproj index 68e195a00847e..2bbb69bb379cd 100644 --- a/src/libraries/System.Private.Xml/src/System.Private.Xml.csproj +++ b/src/libraries/System.Private.Xml/src/System.Private.Xml.csproj @@ -759,7 +759,10 @@ - + @@ -785,8 +788,4 @@ - - - -