2 // System.Xml.XmlTextWriter
5 // Kral Ferch <kral_ferch@hotmail.com>
11 using System.Collections;
17 public class XmlTextWriter : XmlWriter
21 protected TextWriter w;
22 protected bool nullEncoding = false;
23 protected bool openWriter = true;
24 protected bool openStartElement;
25 protected bool documentStarted = false;
26 protected bool namespaces = true;
27 protected Stack openElements = new Stack ();
28 protected XmlNamespaceManager namespaceManager = new XmlNamespaceManager (new NameTable ());
29 protected Formatting formatting = Formatting.None;
30 protected int indentation = 2;
31 protected char indentChar = ' ';
32 protected string indentChars = " ";
33 protected char quoteChar = '\"';
34 protected int indentLevel = 0;
35 protected string indentFormatting;
36 protected Stream baseStream = null;
42 public XmlTextWriter (TextWriter w) : base ()
47 baseStream = ((StreamWriter)w).BaseStream;
52 public XmlTextWriter (Stream w, Encoding encoding) : base ()
54 if (encoding == null) {
56 encoding = new UTF8Encoding ();
59 this.w = new StreamWriter(w, encoding);
63 public XmlTextWriter (string filename, Encoding encoding) : base ()
65 this.w = new StreamWriter(filename, false, encoding);
66 baseStream = ((StreamWriter)w).BaseStream;
73 public Stream BaseStream {
74 get { return baseStream; }
78 public Formatting Formatting {
79 get { return formatting; }
80 set { formatting = value; }
83 public bool IndentingOverriden
86 if (openElements.Count == 0)
89 return (((XmlTextWriterOpenElement)openElements.Peek()).IndentingOverriden);
92 if (openElements.Count > 0)
93 ((XmlTextWriterOpenElement)openElements.Peek()).IndentingOverriden = value;
97 public int Indentation {
98 get { return indentation; }
101 UpdateIndentChars ();
105 public char IndentChar {
106 get { return indentChar; }
109 UpdateIndentChars ();
113 public bool Namespaces {
114 get { return namespaces; }
116 if (ws != WriteState.Start)
117 throw new InvalidOperationException ("NotInWriteState.");
124 public char QuoteChar {
125 get { return quoteChar; }
127 if ((value != '\'') && (value != '\"'))
128 throw new ArgumentException ("This is an invalid XML attribute quote character. Valid attribute quote characters are ' and \".");
134 public override WriteState WriteState {
139 public override string XmlLang {
140 get { throw new NotImplementedException(); }
144 public override XmlSpace XmlSpace {
145 get { throw new NotImplementedException(); }
152 private void CheckState ()
155 throw new InvalidOperationException ("The Writer is closed.");
158 if ((documentStarted == true) && (formatting == Formatting.Indented) && (!IndentingOverriden)) {
159 indentFormatting = "\r\n";
160 if (indentLevel > 0) {
161 for (int i = 0; i < indentLevel; i++)
162 indentFormatting += indentChars;
166 indentFormatting = "";
168 documentStarted = true;
171 public override void Close ()
173 while (openElements.Count > 0) {
178 ws = WriteState.Closed;
182 private void CloseStartElement ()
184 if (openStartElement)
187 ws = WriteState.Content;
188 openStartElement = false;
192 public override void Flush ()
198 public override string LookupPrefix (string ns)
200 throw new NotImplementedException ();
203 private void UpdateIndentChars ()
206 for (int i = 0; i < indentation; i++)
207 indentChars += indentChar;
211 public override void WriteBase64 (byte[] buffer, int index, int count)
213 throw new NotImplementedException ();
217 public override void WriteBinHex (byte[] buffer, int index, int count)
219 throw new NotImplementedException ();
222 public override void WriteCData (string text)
224 if (text.IndexOf("]]>") > 0)
226 throw new ArgumentException ();
230 CloseStartElement ();
232 w.Write("<![CDATA[{0}]]>", text);
236 public override void WriteCharEntity (char ch)
238 throw new NotImplementedException ();
242 public override void WriteChars (char[] buffer, int index, int count)
244 throw new NotImplementedException ();
247 public override void WriteComment (string text)
249 if ((text.EndsWith("-")) || (text.IndexOf("-->") > 0)) {
250 throw new ArgumentException ();
254 CloseStartElement ();
256 w.Write ("<!--{0}-->", text);
260 public override void WriteDocType (string name, string pubid, string sysid, string subset)
262 throw new NotImplementedException ();
266 public override void WriteEndAttribute ()
268 throw new NotImplementedException ();
272 public override void WriteEndDocument ()
274 throw new NotImplementedException ();
277 public override void WriteEndElement ()
279 if (openElements.Count == 0)
280 throw new InvalidOperationException("There was no XML start tag open.");
286 if (openStartElement) {
289 openStartElement = false;
292 w.Write ("{0}</{1}>", indentFormatting, openElements.Pop ());
293 namespaceManager.PopScope();
298 public override void WriteEntityRef (string name)
300 throw new NotImplementedException ();
304 public override void WriteFullEndElement ()
306 throw new NotImplementedException ();
310 public override void WriteName (string name)
312 throw new NotImplementedException ();
316 public override void WriteNmToken (string name)
318 throw new NotImplementedException ();
321 public override void WriteProcessingInstruction (string name, string text)
323 if ((name == null) || (name == string.Empty) || (name.IndexOf("?>") > 0) || (text.IndexOf("?>") > 0)) {
324 throw new ArgumentException ();
328 CloseStartElement ();
330 w.Write ("{0}<?{1} {2}?>", indentFormatting, name, text);
334 public override void WriteQualifiedName (string localName, string ns)
336 throw new NotImplementedException ();
340 public override void WriteRaw (string data)
342 throw new NotImplementedException ();
346 public override void WriteRaw (char[] buffer, int index, int count)
348 throw new NotImplementedException ();
352 public override void WriteStartAttribute (string prefix, string localName, string ns)
354 throw new NotImplementedException ();
357 public override void WriteStartDocument ()
359 WriteStartDocument ("");
362 public override void WriteStartDocument (bool standalone)
364 string standaloneFormatting;
366 if (standalone == true)
367 standaloneFormatting = " standalone=\"yes\"";
369 standaloneFormatting = " standalone=\"no\"";
371 WriteStartDocument (standaloneFormatting);
374 private void WriteStartDocument (string standaloneFormatting)
376 if (documentStarted == true)
377 throw new InvalidOperationException("WriteStartDocument should be the first call.");
381 string encodingFormatting = "";
384 encodingFormatting = " encoding=\"" + w.Encoding.HeaderName + "\"";
386 w.Write("<?xml version=\"1.0\"{0}{1}?>", encodingFormatting, standaloneFormatting);
387 ws = WriteState.Prolog;
390 public override void WriteStartElement (string prefix, string localName, string ns)
392 if (!Namespaces && (((prefix != null) && (prefix != String.Empty))
393 || ((ns != null) && (ns != String.Empty))))
394 throw new ArgumentException ("Cannot set the namespace if Namespaces is 'false'.");
396 WriteStartElementInternal (prefix, localName, ns);
399 protected override void WriteStartElementInternal (string prefix, string localName, string ns)
402 prefix = String.Empty;
407 if ((prefix != String.Empty) && ((ns == null) || (ns == String.Empty)))
408 throw new ArgumentException ("Cannot use a prefix with an empty namespace.");
411 CloseStartElement ();
413 string formatXmlns = "";
414 string formatPrefix = "";
416 if (ns != String.Empty)
418 string existingPrefix = namespaceManager.LookupPrefix (ns);
420 if (prefix == String.Empty)
421 prefix = existingPrefix;
423 if (prefix != existingPrefix)
424 formatXmlns = " xmlns:" + prefix + "=\"" + ns + "\"";
425 else if (existingPrefix == String.Empty)
426 formatXmlns = " xmlns=\"" + ns + "\"";
428 else if ((prefix == String.Empty) && (namespaceManager.LookupNamespace(prefix) != String.Empty)) {
429 formatXmlns = " xmlns=\"\"";
432 if (prefix != String.Empty) {
433 formatPrefix = prefix + ":";
436 w.Write ("{0}<{1}{2}{3}", indentFormatting, formatPrefix, localName, formatXmlns);
438 openElements.Push (new XmlTextWriterOpenElement (formatPrefix + localName));
439 ws = WriteState.Element;
440 openStartElement = true;
442 namespaceManager.PushScope ();
443 namespaceManager.AddNamespace (prefix, ns);
448 [MonoTODO("Haven't done any entity replacements yet.")]
449 public override void WriteString (string text)
451 if (text != String.Empty) {
453 CloseStartElement ();
457 IndentingOverriden = true;
461 public override void WriteSurrogateCharEntity (char lowChar, char highChar)
463 throw new NotImplementedException ();
467 public override void WriteWhitespace (string ws)
469 throw new NotImplementedException ();