void WriteNode (XmlNode node)
		{
			XmlFormattingSettings oldFormat = formatSettings;
			SetFormat (node);
			
			switch (node.NodeType) {
				case XmlNodeType.Document: {
					WriteContent (node);
					break;
				}
				case XmlNodeType.Attribute: {
					XmlAttribute at = (XmlAttribute) node;
					if (at.Specified) {
						WriteStartAttribute (at.NamespaceURI.Length > 0 ? at.Prefix : String.Empty, at.LocalName, at.NamespaceURI);
						WriteContent (node);
						WriteEndAttribute ();
					}
					break;
				}
				case XmlNodeType.CDATA: {
					WriteCData (((XmlCDataSection)node).Data);
					break;
				}
				case XmlNodeType.Comment: {
					WriteComment (((XmlComment)node).Data);
					break;
				}
				case XmlNodeType.DocumentFragment: {
					for (int i = 0; i < node.ChildNodes.Count; i++)
						WriteNode (node.ChildNodes [i]);
					break;
				}
				case XmlNodeType.DocumentType: {
					XmlDocumentType dt = (XmlDocumentType) node;
					WriteDocType (dt.Name, dt.PublicId, dt.SystemId, dt.InternalSubset);
					break;
				}
				case XmlNodeType.Element: {
					XmlElement elem = (XmlElement) node;
					WriteStartElement (
						elem.NamespaceURI == null || elem.NamespaceURI.Length == 0 ? String.Empty : elem.Prefix,
						elem.LocalName,
						elem.NamespaceURI);
		
					if (elem.HasAttributes) {
						int oldBeforeSp = formatSettings.SpacesBeforeAssignment;
						int maxLen = 0;
						if (formatSettings.AlignAttributeValues) {
							foreach (XmlAttribute at in elem.Attributes) {
								string name = GetAttributeName (at);
								if (name.Length > maxLen)
									maxLen = name.Length;
							}
						}
						foreach (XmlAttribute at in elem.Attributes) {
							if (formatSettings.AlignAttributeValues) {
								string name = GetAttributeName (at);
								formatSettings.SpacesBeforeAssignment = (maxLen - name.Length) + oldBeforeSp;
							}
							WriteNode (at);
						}
						formatSettings.SpacesBeforeAssignment = oldBeforeSp;
					}
					
					if (!elem.IsEmpty) {
						CloseStartElement ();
						WriteContent (elem);
						WriteFullEndElement ();
					}
					else
						WriteEndElement ();
					break;
				}
				case XmlNodeType.EntityReference: {
					XmlEntityReference eref = (XmlEntityReference) node;
					WriteRaw ("&");
					WriteName (eref.Name);
					WriteRaw (";");
					break;
				}
				case XmlNodeType.ProcessingInstruction: {
					XmlProcessingInstruction pi = (XmlProcessingInstruction) node;
					WriteProcessingInstruction (pi.Target, pi.Data);
					break;
				}
				case XmlNodeType.SignificantWhitespace: {
					XmlSignificantWhitespace wn = (XmlSignificantWhitespace) node;
					WriteWhitespace (wn.Data);
					break;
				}
				case XmlNodeType.Text: {
					XmlText t = (XmlText) node;
					WriteString (t.Data);
					break;
				}
				case XmlNodeType.Whitespace: {
					XmlWhitespace wn = (XmlWhitespace) node;
					WriteWhitespace (wn.Data);
					break;
				}
				case XmlNodeType.XmlDeclaration: {
					XmlDeclaration dec = (XmlDeclaration) node;
					WriteRaw (String.Format ("<?xml {0}?>", dec.Value));
					break;
				}
			}
			formatSettings = oldFormat;
		}
		void SetFormat (XmlNode node)
		{
			XmlFormattingSettings s;
			if (formatMap.TryGetValue (node, out s)) {
				formatSettings = s;
			}
			else {
				if (node is XmlElement)
					formatSettings = defaultFormatSettings;
			}
		}
		public void WriteNode (XmlNode node, XmlFormattingPolicy formattingPolicy, TextStylePolicy textPolicy)
		{
			this.TextPolicy = textPolicy;
			formatMap.Clear ();
			defaultFormatSettings = formattingPolicy.DefaultFormat;
			foreach (XmlFormattingSettings format in formattingPolicy.Formats) {
				foreach (string xpath in format.ScopeXPath) {
					foreach (XmlNode n in node.SelectNodes (xpath))
						formatMap [n] = format;
				}
			}
			WriteNode (node);
		}
		protected virtual void OnButtonAddClicked (object sender, EventArgs e)
		{
			var format = new XmlFormattingSettings ();
			policy.Formats.Add (format);
			TreeIter it = AppendSettings (format);
			listView.Selection.SelectIter (it);
		}
		void FillFormat (XmlFormattingSettings format)
		{
			currentFormat = format;
			if (currentFormat != null && currentFormat.ScopeXPath.Count == 0)
				currentFormat.ScopeXPath.Add ("");
			propertyGrid.CurrentObject = format;
			UpdateScopes ();
			propertyGrid.Sensitive = currentFormat != null;
		}
		string GetName (XmlFormattingSettings format)
		{
			if (format == policy.DefaultFormat)
				return GettextCatalog.GetString ("Default");
			
			string name = "";
			foreach (string s in format.ScopeXPath) {
				if (name.Length != 0)
					name += ", ";
				name += s;
			}
			if (name.Length != 0)
				return name;
			else {
				int i = policy.Formats.IndexOf (format) + 1;
				return string.Format (GettextCatalog.GetString ("Format #{0}"), i);
			}
		}
		TreeIter AppendSettings (XmlFormattingSettings format)
		{
			return store.AppendValues (GetName (format), format);
		}