public static TextFormatInfo GetTextFormatInfo (string file) { var info = new TextFormatInfo (); string newLine = null; ByteOrderMark bom; using (FileStream fs = File.OpenRead (file)) { byte[] buf = new byte [1024]; int nread, i; if ((nread = fs.Read (buf, 0, buf.Length)) <= 0) return info; if (ByteOrderMark.TryParse (buf, nread, out bom)) i = bom.Length; else i = 0; do { // Read to the first newline to figure out which line endings this file is using while (i < nread) { if (buf[i] == '\r') { newLine = "\r\n"; break; } else if (buf[i] == '\n') { newLine = "\n"; break; } i++; } if (newLine == null) { if ((nread = fs.Read (buf, 0, buf.Length)) <= 0) { newLine = "\n"; break; } i = 0; } } while (newLine == null); // Check for a blank line at the end info.EndsWithEmptyLine = fs.Seek (-1, SeekOrigin.End) > 0 && fs.ReadByte () == (int) '\n'; info.NewLine = newLine; info.ByteOrderMark = bom; return info; } }
public static void FormatElement (TextFormatInfo format, XmlElement elem) { // Remove duplicate namespace declarations var nsa = elem.Attributes ["xmlns"]; if (nsa != null && nsa.Value == MSBuildProject.Schema) elem.Attributes.Remove (nsa); foreach (var e in elem.ChildNodes.OfType<XmlElement> ().ToArray ()) { Indent (format, e, false); FormatElement (format, e); } }
internal void Load (string file, MSBuildXmlReader reader) { AssertCanModify (); try { this.file = file; IsNewProject = false; format = FileUtil.GetTextFormatInfo (file); // HACK: XmlStreamReader will fail if the file is encoded in UTF-8 but has <?xml version="1.0" encoding="utf-16"?> // To work around this, we load the XML content into a string and use XmlDocument.LoadXml() instead. string xml = File.ReadAllText (file); LoadXml (xml, reader); } finally { EnableChangeTracking (); } }
static void SetIndent (TextFormatInfo format, XmlElement elem, string indent) { if (string.IsNullOrEmpty (indent) || elem.ParentNode == null) return; bool foundLineBreak = RemoveIndent (elem.PreviousSibling); string newIndent = foundLineBreak ? indent : format.NewLine + indent; var ws = elem.OwnerDocument.CreateWhitespace (newIndent); if (elem.ParentNode is XmlDocument) { // MS.NET doesn't allow inserting whitespace if there is a document element. The workaround // is to remove the element, add the space, then add back the element var doc = elem.OwnerDocument; doc.RemoveChild (elem); doc.AppendChild (ws); doc.AppendChild (elem); } else elem.ParentNode.InsertBefore (ws, elem); if (elem.ChildNodes.OfType<XmlElement> ().Any ()) { foundLineBreak = RemoveIndent (elem.LastChild); newIndent = foundLineBreak ? indent : format.NewLine + indent; elem.AppendChild (elem.OwnerDocument.CreateWhitespace (newIndent)); } }
static void Indent (TextFormatInfo format, XmlElement elem, string indent) { SetIndent (format, elem, indent); foreach (var c in elem.ChildNodes.OfType<XmlElement> ()) Indent (format, c, indent + " "); }
public static void Indent (TextFormatInfo format, XmlElement elem, bool closeInNewLine) { var prev = FindPreviousSibling (elem); string indent; if (prev != null) indent = GetIndentString (prev); else if (elem != elem.OwnerDocument.DocumentElement) indent = GetIndentString (elem.ParentNode) + " "; else indent = ""; Indent (format, elem, indent); if (elem.ChildNodes.Count == 0 && closeInNewLine) { var ws = elem.OwnerDocument.CreateWhitespace (format.NewLine + indent); elem.AppendChild (ws); } if (elem.NextSibling is XmlElement) SetIndent (format, (XmlElement)elem.NextSibling, indent); if (elem.NextSibling == null && elem != elem.OwnerDocument.DocumentElement && elem.ParentNode != null) { var parentIndent = GetIndentString (elem.ParentNode); var ws = elem.OwnerDocument.CreateWhitespace (format.NewLine + parentIndent); elem.ParentNode.InsertAfter (ws, elem); } }