public override void Save(Stream stream) { if (stream == null) { throw new ArgumentNullException(nameof(stream)); } XmlWriter xmlWriter = null; try { if (PreserveWhitespace) { XmlFormatter.Format(this); xmlWriter = new XmlAttributePreservingWriter(stream, TextEncoding); } else { XmlTextWriter textWriter = new XmlTextWriter(stream, TextEncoding) { Formatting = Formatting.Indented }; xmlWriter = textWriter; } WriteTo(xmlWriter); } finally { xmlWriter?.Flush(); } }
public static void Format(XmlDocument document) { if (document is XmlFileInfoDocument errorInfoDocument) { var formatter = new XmlFormatter(errorInfoDocument); formatter.FormatLoop(errorInfoDocument); } }
public override void Save(string filename) { if (string.IsNullOrWhiteSpace(filename)) { throw new ArgumentException("File name cannot be empty", nameof(filename)); } XmlWriter xmlWriter = null; try { if (PreserveWhitespace) { XmlFormatter.Format(this); xmlWriter = new XmlAttributePreservingWriter(filename, TextEncoding); } else { var textWriter = new XmlTextWriter(filename, TextEncoding) { Formatting = Formatting.Indented }; xmlWriter = textWriter; } WriteTo(xmlWriter); } finally { if (xmlWriter != null) { xmlWriter.Flush(); xmlWriter.Close(); } } }
void IXmlFormattableAttributes.FormatAttributes(XmlFormatter formatter) => _preservationDict.UpdatePreservationInfo(Attributes, formatter);
void EnsureAttributeNewLineString(XmlFormatter formatter) => GetAttributeNewLineString(formatter);
internal void UpdatePreservationInfo(XmlAttributeCollection updatedAttributes, XmlFormatter formatter) { if (updatedAttributes.Count == 0) { if (_orderedAttributes.Count <= 0) { return; } // All attributes were removed, clear preservation info _leadingSpaces.Clear(); _orderedAttributes.Clear(); } else { var attributeExists = new Dictionary <string, bool>(); // Prepopulate the list with attributes that existed before foreach (string attributeName in _orderedAttributes) { attributeExists[attributeName] = false; } // Update the list with attributes that exist now foreach (XmlAttribute attribute in updatedAttributes) { if (!attributeExists.ContainsKey(attribute.Name)) { _orderedAttributes.Add(attribute.Name); } attributeExists[attribute.Name] = true; } var firstAttribute = true; string?keepLeadingWhitespace = null; foreach (string key in _orderedAttributes) { bool exists = attributeExists[key]; // Handle removal if (!exists) { // We need to figure out whether to keep the leading // or trailing whitespace. The logic is: // 1. The whitespace before the first attribute is // always kept, so remove trailing space. // 2. We want to keep newlines, so if the leading // space contains a newline then remove trailing // space. If multiple newlines are being removed, // keep the last one. // 3. Otherwise, remove leading space. // // In order to remove trailing space, we have to // remove the leading space of the next attribute, so // we store this leading space to replace the next. if (_leadingSpaces.ContainsKey(key)) { string leadingSpace = _leadingSpaces[key]; if (firstAttribute) { keepLeadingWhitespace ??= leadingSpace; } else if (ContainsNewLine(leadingSpace)) { keepLeadingWhitespace = leadingSpace; } _leadingSpaces.Remove(key); } } else if (keepLeadingWhitespace is not null) { // Exception to rule #2 above: Don't replace an existing // newline with one that was removed if (firstAttribute || !_leadingSpaces.ContainsKey(key) || !ContainsNewLine(_leadingSpaces[key])) { _leadingSpaces[key] = keepLeadingWhitespace; } keepLeadingWhitespace = null; } // Handle addition else if (!_leadingSpaces.ContainsKey(key)) { if (firstAttribute) { // This will prevent the textwriter from writing a // newline before the first attribute _leadingSpaces[key] = " "; } else if (OneAttributePerLine) { // Add the indent space between each attribute _leadingSpaces[key] = GetAttributeNewLineString(formatter) !; } else { // Don't add any hard-coded spaces. All new attributes // should be at the end, so they'll be formatted while // writing. Make sure we have the right indent string, // though. EnsureAttributeNewLineString(formatter); } } // firstAttribute remains true until we find the first // attribute that actually exists firstAttribute = firstAttribute && !exists; } } }
string ComputeAttributeNewLineString(XmlFormatter formatter) => LookAheadForNewLineString() ?? formatter?.CurrentAttributeIndent;
public string GetAttributeNewLineString(XmlFormatter formatter) => _attributeNewLineString ?? (_attributeNewLineString = ComputeAttributeNewLineString(formatter));