using System.Collections.Generic;
using System.Xml.Serialization;
public class NoEndBracketEscapingXmlWriter : XmlWriterDecorator
public NoEndBracketEscapingXmlWriter(XmlWriter baseWriter) : base(baseWriter) { }
public override void WriteString(string text)
int prevIndex = 0, index;
while ((index = text.IndexOf('>', prevIndex)) >= 0)
buffer = text.ToCharArray();
if (text.AsSpan().Slice(index + 1).StartsWith(" ") && text.AsSpan().Slice(prevIndex, index - prevIndex).EndsWith(" ]]"))
base.WriteChars(buffer, prevIndex, index - prevIndex + 1);
base.WriteChars(buffer, prevIndex, index - prevIndex);
else if (prevIndex < buffer.Length)
base.WriteChars(buffer, prevIndex, buffer.Length - prevIndex);
public class XmlWriterDecorator : XmlWriter
readonly XmlWriter baseWriter;
public XmlWriterDecorator(XmlWriter baseWriter) => this.baseWriter = baseWriter ?? throw new ArgumentNullException();
protected virtual bool IsSuspended { get { return false; } }
public override void Close() => baseWriter.Close();
public override void Flush() => baseWriter.Flush();
public override string LookupPrefix(string ns) => baseWriter.LookupPrefix(ns);
public override void WriteBase64(byte[] buffer, int index, int count)
baseWriter.WriteBase64(buffer, index, count);
public override void WriteCData(string text)
baseWriter.WriteCData(text);
public override void WriteCharEntity(char ch)
baseWriter.WriteCharEntity(ch);
public override void WriteChars(char[] buffer, int index, int count)
baseWriter.WriteChars(buffer, index, count);
public override void WriteComment(string text)
baseWriter.WriteComment(text);
public override void WriteDocType(string name, string pubid, string sysid, string subset)
baseWriter.WriteDocType(name, pubid, sysid, subset);
public override void WriteEndAttribute()
baseWriter.WriteEndAttribute();
public override void WriteEndDocument()
baseWriter.WriteEndDocument();
public override void WriteEndElement()
baseWriter.WriteEndElement();
public override void WriteEntityRef(string name)
baseWriter.WriteEntityRef(name);
public override void WriteFullEndElement()
baseWriter.WriteFullEndElement();
public override void WriteProcessingInstruction(string name, string text)
baseWriter.WriteProcessingInstruction(name, text);
public override void WriteRaw(string data)
baseWriter.WriteRaw(data);
public override void WriteRaw(char[] buffer, int index, int count)
baseWriter.WriteRaw(buffer, index, count);
public override void WriteStartAttribute(string prefix, string localName, string ns)
baseWriter.WriteStartAttribute(prefix, localName, ns);
public override void WriteStartDocument(bool standalone) => baseWriter.WriteStartDocument(standalone);
public override void WriteStartDocument() => baseWriter.WriteStartDocument();
public override void WriteStartElement(string prefix, string localName, string ns)
baseWriter.WriteStartElement(prefix, localName, ns);
public override WriteState WriteState => baseWriter.WriteState;
public override void WriteString(string text)
baseWriter.WriteString(text);
public override void WriteSurrogateCharEntity(char lowChar, char highChar)
baseWriter.WriteSurrogateCharEntity(lowChar, highChar);
public override void WriteWhitespace(string ws)
baseWriter.WriteWhitespace(ws);
public static class XNodeExtensions
public static string ToStringNoEndBracketEscaping(this XNode node)
throw new ArgumentNullException(nameof(node));
using var textWriter = new StringWriter();
using (var innerWriter = XmlWriter.Create(textWriter, new XmlWriterSettings { Indent = true, OmitXmlDeclaration = true }))
using (var writer = new NoEndBracketEscapingXmlWriter(innerWriter))
return textWriter.ToString();
public static void Test()
var xmlString = @"<?xml version=""1.0"" encoding=""utf-8""?><Foo Name=""a->b""></Foo>";
var doc = XDocument.Parse(xmlString);
foreach (var element in doc.Root.DescendantsAndSelf())
Console.Write("Attributes for element {0}: ", element.Name);
foreach (var attr in doc.Root.Attributes())
Console.Write("\"{0}\": \"{1}\"{2}", attr.Name, attr.Value, i++ == 0 ? "" : ", ");
var newXml = doc.ToStringNoEndBracketEscaping();
Console.WriteLine("\nRe-serialized XDocument without > escaping:");
Console.WriteLine(newXml);
Console.WriteLine("\nRe-serialized XDocument:");
Console.WriteLine(doc.ToString());
public static void Main()
Console.WriteLine("Environment version: {0} ({1}, {2})", System.Runtime.InteropServices.RuntimeInformation.FrameworkDescription , Environment.Version, Environment.OSVersion);
Console.WriteLine("Failed with unhandled exception: ");