PageRenderTime 30ms CodeModel.GetById 12ms app.highlight 12ms RepoModel.GetById 1ms app.codeStats 0ms

/AvalonEdit/ICSharpCode.AvalonEdit/Xml/CanonicalPrintAXmlVisitor.cs

http://github.com/icsharpcode/ILSpy
C# | 119 lines | 92 code | 10 blank | 17 comment | 18 complexity | 91d939e5cfce2eda435eb620f563d48a MD5 | raw file
  1// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
  2// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
  3
  4using System;
  5using System.Linq;
  6using System.Text;
  7
  8namespace ICSharpCode.AvalonEdit.Xml
  9{
 10	/// <summary>
 11	/// Converts the XML tree back to text in canonical form.
 12	/// See http://www.w3.org/TR/xml-c14n
 13	/// </summary>
 14	public class CanonicalPrintAXmlVisitor: AbstractAXmlVisitor
 15	{
 16		StringBuilder sb = new StringBuilder();
 17		
 18		/// <summary>
 19		/// Gets the pretty printed text
 20		/// </summary>
 21		public string Output {
 22			get {
 23				return sb.ToString();
 24			}
 25		}
 26		
 27		/// <summary> Create canonical text from a document </summary>
 28		public static string Print(AXmlDocument doc)
 29		{
 30			CanonicalPrintAXmlVisitor visitor = new CanonicalPrintAXmlVisitor();
 31			visitor.VisitDocument(doc);
 32			return visitor.Output;
 33		}
 34		
 35		/// <summary> Visit RawDocument </summary>
 36		public override void VisitDocument(AXmlDocument document)
 37		{
 38			foreach(AXmlObject child in document.Children) {
 39				AXmlTag childAsTag = child as AXmlTag;
 40				// Only procssing instructions or elements
 41				if (childAsTag != null && childAsTag.IsProcessingInstruction && childAsTag.Name != "xml") {
 42					VisitTag(childAsTag);
 43				} else {
 44					AXmlElement childAsElement = child as AXmlElement;
 45					if (childAsElement != null) {
 46						VisitElement(childAsElement);
 47					}
 48				}
 49			}
 50		}
 51		
 52		/// <summary> Visit RawElement </summary>
 53		public override void VisitElement(AXmlElement element)
 54		{
 55			base.VisitElement(element);
 56		}
 57		
 58		/// <summary> Visit RawTag </summary>
 59		public override void VisitTag(AXmlTag tag)
 60		{
 61			if (tag.IsStartOrEmptyTag) {
 62				sb.Append('<');
 63				sb.Append(tag.Name);
 64				foreach(AXmlAttribute attr in tag.Children.OfType<AXmlAttribute>().OrderBy(a => a.Name)) {
 65					VisitAttribute(attr);
 66				}
 67				sb.Append('>');
 68				if (tag.IsEmptyTag) {
 69					// Use explicit start-end pair
 70					sb.AppendFormat("</{0}>", tag.Name);
 71				}
 72			} else if (tag.IsEndTag) {
 73				sb.AppendFormat("</{0}>", tag.Name);
 74			} else if (tag.IsProcessingInstruction) {
 75				sb.Append("<?");
 76				sb.Append(tag.Name);
 77				foreach(AXmlText text in tag.Children.OfType<AXmlText>()) {
 78					sb.Append(text.Value);
 79				}
 80				if (tag.Children.Count == 0)
 81					sb.Append(' ');
 82				sb.Append("?>");
 83			} else if (tag.IsCData) {
 84				foreach(AXmlText text in tag.Children.OfType<AXmlText>()) {
 85					sb.Append(Escape(text.Value));
 86				}
 87			}
 88		}
 89		
 90		/// <summary> Visit RawAttribute </summary>
 91		public override void VisitAttribute(AXmlAttribute attribute)
 92		{
 93			sb.Append(' ');
 94			sb.Append(attribute.Name);
 95			sb.Append("=");
 96			sb.Append('"');
 97			sb.Append(Escape(attribute.Value));
 98			sb.Append('"');
 99		}
100		
101		/// <summary> Visit RawText </summary>
102		public override void VisitText(AXmlText text)
103		{
104			sb.Append(Escape(text.Value));
105		}
106		
107		static string Escape(string text)
108		{
109			return text
110				.Replace("&", "&amp;")
111				.Replace("<", "&lt;")
112				.Replace(">", "&gt;")
113				.Replace("\"", "&quot;")
114				.Replace("\u0009", "&#9;")
115				.Replace("\u000A", "&#10;")
116				.Replace("\u000D", "&#13;");
117		}
118	}
119}