Example #1
0
		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);
			}
		}