2 // System.Xml.XmlWriter
5 // Kral Ferch <kral_ferch@hotmail.com>
6 // Atsushi Enomoto <ginga@kit.hi-ho.ne.jp>
9 // (C) 2002-2003 Atsushi Enomoto
13 // Permission is hereby granted, free of charge, to any person obtaining
14 // a copy of this software and associated documentation files (the
15 // "Software"), to deal in the Software without restriction, including
16 // without limitation the rights to use, copy, modify, merge, publish,
17 // distribute, sublicense, and/or sell copies of the Software, and to
18 // permit persons to whom the Software is furnished to do so, subject to
19 // the following conditions:
21 // The above copyright notice and this permission notice shall be
22 // included in all copies or substantial portions of the Software.
24 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
28 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
29 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
30 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
37 using System.Xml.XPath;
43 public abstract class XmlWriter : IDisposable
45 public abstract class XmlWriter
49 XmlWriterSettings settings;
54 protected XmlWriter () { }
61 public virtual XmlWriterSettings Settings {
64 settings = new XmlWriterSettings ();
70 public abstract WriteState WriteState { get; }
74 public virtual string XmlLang {
78 public virtual XmlSpace XmlSpace {
79 get { return XmlSpace.None; }
82 public abstract string XmlLang { get; }
84 public abstract XmlSpace XmlSpace { get; }
91 public abstract void Close ();
94 public static XmlWriter Create (Stream stream)
96 return Create (stream, null);
99 public static XmlWriter Create (string file)
101 return Create (file, null);
104 public static XmlWriter Create (TextWriter writer)
106 return Create (writer, null);
109 public static XmlWriter Create (XmlWriter writer)
111 return Create (writer, null);
114 public static XmlWriter Create (StringBuilder builder)
116 return Create (builder, null);
119 [MonoTODO ("NewLineHandling/OutputMethod")]
120 public static XmlWriter Create (Stream stream, XmlWriterSettings settings)
122 // FIXME: this might result in encoding null reference
123 Encoding enc = settings != null ? settings.Encoding : Encoding.UTF8;
124 return Create (new StreamWriter (stream, enc), settings);
127 [MonoTODO ("NewLineHandling/OutputMethod")]
128 public static XmlWriter Create (string file, XmlWriterSettings settings)
130 // FIXME: this might result in encoding null reference
131 Encoding enc = settings != null ? settings.Encoding : Encoding.UTF8;
132 return Create (new StreamWriter (file, false, enc), settings);
135 [MonoTODO ("NewLineHandling/OutputMethod")]
136 public static XmlWriter Create (StringBuilder builder, XmlWriterSettings settings)
138 return Create (new StringWriter (builder), null);
141 [MonoTODO ("NewLineHandling/OutputMethod")]
142 public static XmlWriter Create (TextWriter writer, XmlWriterSettings settings)
144 return CreateTextWriter (writer, settings);
147 [MonoTODO ("NewLineHandling/OutputMethod")]
148 public static XmlWriter Create (XmlWriter writer, XmlWriterSettings settings)
150 if (settings == null)
151 settings = new XmlWriterSettings ();
152 writer.settings = settings;
156 private static XmlWriter CreateTextWriter (TextWriter writer, XmlWriterSettings settings)
158 if (settings == null)
159 settings = new XmlWriterSettings ();
160 XmlTextWriter xtw = new XmlTextWriter (writer);
161 // Indent, IndentChars
162 if (settings.Indent) {
163 xtw.Formatting = Formatting.Indented;
164 xtw.IndentChars = settings.IndentChars;
165 xtw.NewLineOnAttributes = settings.NewLineOnAttributes;
168 xtw.NewLineChars = settings.NewLineChars;
170 xtw.CloseOutput = settings.CloseOutput;
172 xtw.ConformanceLevel = settings.ConformanceLevel;
173 // OmitXmlDeclaration
174 xtw.OmitXmlDeclaration = settings.OmitXmlDeclaration;
176 xtw.CheckCharacters = settings.CheckCharacters;
177 return Create (xtw, settings);
180 public virtual void Dispose (bool disposing)
185 void IDisposable.Dispose ()
191 public abstract void Flush ();
193 public abstract string LookupPrefix (string ns);
195 private void WriteAttribute (XmlReader reader, bool defattr)
197 if (!defattr && reader.IsDefault)
200 WriteStartAttribute (reader.Prefix, reader.LocalName, reader.NamespaceURI);
201 while (reader.ReadAttributeValue ()) {
202 switch (reader.NodeType) {
203 case XmlNodeType.Text:
204 WriteString (reader.Value);
206 case XmlNodeType.EntityReference:
207 WriteEntityRef (reader.Name);
211 WriteEndAttribute ();
214 public virtual void WriteAttributes (XmlReader reader, bool defattr)
217 throw new ArgumentException("null XmlReader specified.", "reader");
219 switch (reader.NodeType) {
220 case XmlNodeType.XmlDeclaration:
221 WriteAttributeString ("version", reader ["version"]);
222 if (reader ["encoding"] != null)
223 WriteAttributeString ("encoding", reader ["encoding"]);
224 if (reader ["standalone"] != null)
225 WriteAttributeString ("standalone", reader ["standalone"]);
227 case XmlNodeType.Element:
228 if (reader.MoveToFirstAttribute ())
229 goto case XmlNodeType.Attribute;
231 case XmlNodeType.Attribute:
233 WriteAttribute (reader, defattr);
234 } while (reader.MoveToNextAttribute ());
235 reader.MoveToElement ();
238 throw new XmlException("NodeType is not one of Element, Attribute, nor XmlDeclaration.");
242 public void WriteAttributeString (string localName, string value)
244 WriteAttributeString ("", localName, null, value);
247 public void WriteAttributeString (string localName, string ns, string value)
249 WriteAttributeString ("", localName, ns, value);
252 public void WriteAttributeString (string prefix, string localName, string ns, string value)
254 // In MS.NET (1.0), this check is done *here*, not at WriteStartAttribute.
255 // (XmlTextWriter.WriteStartAttribute("xmlns", "anyname", null) throws an exception.
258 if ((prefix == "xmlns" || (prefix == "" && localName == "xmlns")) && ns == null)
259 ns = "http://www.w3.org/2000/xmlns/";
262 WriteStartAttribute (prefix, localName, ns);
264 WriteEndAttribute ();
267 public abstract void WriteBase64 (byte[] buffer, int index, int count);
270 public virtual void WriteBinHex (byte [] buffer, int index, int count)
272 StringWriter sw = new StringWriter ();
273 XmlConvert.WriteBinHex (buffer, index, count, sw);
274 WriteString (sw.ToString ());
277 public abstract void WriteBinHex (byte[] buffer, int index, int count);
280 public abstract void WriteCData (string text);
282 public abstract void WriteCharEntity (char ch);
284 public abstract void WriteChars (char[] buffer, int index, int count);
286 public abstract void WriteComment (string text);
288 public abstract void WriteDocType (string name, string pubid, string sysid, string subset);
290 public void WriteElementString (string localName, string value)
292 WriteStartElement(localName);
297 public void WriteElementString (string localName, string ns, string value)
299 WriteStartElement(localName, ns);
305 public void WriteElementString (string prefix, string localName, string ns, string value)
307 WriteStartElement(prefix, localName, ns);
313 public abstract void WriteEndAttribute ();
315 public abstract void WriteEndDocument ();
317 public abstract void WriteEndElement ();
319 public abstract void WriteEntityRef (string name);
321 public abstract void WriteFullEndElement ();
324 public virtual void WriteName (string name)
326 WriteNameInternal (name);
329 public virtual void WriteNmToken (string name)
331 WriteNmTokenInternal (name);
334 public virtual void WriteQualifiedName (string localName, string ns)
336 WriteQualifiedNameInternal (localName, ns);
339 public abstract void WriteName (string name);
341 public abstract void WriteNmToken (string name);
343 public abstract void WriteQualifiedName (string localName, string ns);
346 internal void WriteNameInternal (string name)
349 switch (Settings.ConformanceLevel) {
350 case ConformanceLevel.Document:
351 case ConformanceLevel.Fragment:
352 XmlConvert.VerifyName (name);
356 XmlConvert.VerifyName (name);
361 internal virtual void WriteNmTokenInternal (string name)
364 switch (Settings.ConformanceLevel) {
365 case ConformanceLevel.Document:
366 case ConformanceLevel.Fragment:
367 XmlConvert.VerifyNMTOKEN (name);
371 XmlConvert.VerifyNMTOKEN (name);
376 internal void WriteQualifiedNameInternal (string localName, string ns)
378 if (localName == null || localName == String.Empty)
379 throw new ArgumentException ();
384 switch (Settings.ConformanceLevel) {
385 case ConformanceLevel.Document:
386 case ConformanceLevel.Fragment:
387 XmlConvert.VerifyNCName (localName);
391 XmlConvert.VerifyNCName (localName);
394 string prefix = ns.Length > 0 ? LookupPrefix (ns) : String.Empty;
396 throw new ArgumentException (String.Format ("Namespace '{0}' is not declared.", ns));
398 if (prefix != String.Empty) {
399 WriteString (prefix);
401 WriteString (localName);
404 WriteString (localName);
408 [MonoTODO ("defattr handling")]
409 public virtual void WriteNode (XPathNavigator navigator, bool defattr)
411 if (navigator == null)
412 throw new ArgumentNullException ("navigator");
413 switch (navigator.NodeType) {
414 case XPathNodeType.Attribute:
415 case XPathNodeType.Namespace:
416 WriteAttributeString (navigator.Prefix, navigator.LocalName, navigator.NamespaceURI, navigator.Value);
419 WriteNode (navigator.ReadSubtree (), defattr);
425 public virtual void WriteNode (XmlReader reader, bool defattr)
428 throw new ArgumentException ();
430 if (reader.ReadState == ReadState.Initial) {
433 WriteNode (reader, defattr);
434 } while (!reader.EOF);
438 switch (reader.NodeType) {
439 case XmlNodeType.Element:
440 WriteStartElement (reader.Prefix, reader.LocalName, reader.NamespaceURI);
442 WriteAttributes (reader, defattr);
443 reader.MoveToElement ();
445 // Well, I found that MS.NET took this way, since
446 // there was a error-prone SgmlReader that fails
447 // MoveToNextAttribute().
448 if (reader.HasAttributes) {
449 for (int i = 0; i < reader.AttributeCount; i++) {
450 reader.MoveToAttribute (i);
451 WriteAttribute (reader, defattr);
453 reader.MoveToElement ();
456 if (reader.IsEmptyElement)
459 int depth = reader.Depth;
461 if (reader.NodeType != XmlNodeType.EndElement) {
463 WriteNode (reader, defattr);
464 } while (depth < reader.Depth);
466 WriteFullEndElement ();
469 // In case of XmlAttribute, don't proceed reader, and it will never be written.
470 case XmlNodeType.Attribute:
472 case XmlNodeType.Text:
473 WriteString (reader.Value);
475 case XmlNodeType.CDATA:
476 WriteCData (reader.Value);
478 case XmlNodeType.EntityReference:
479 WriteEntityRef (reader.Name);
481 case XmlNodeType.XmlDeclaration:
482 // LAMESPEC: It means that XmlWriter implementation _must not_ check
483 // whether PI name is "xml" (it is XML error) or not.
484 case XmlNodeType.ProcessingInstruction:
485 WriteProcessingInstruction (reader.Name, reader.Value);
487 case XmlNodeType.Comment:
488 WriteComment (reader.Value);
490 case XmlNodeType.DocumentType:
491 WriteDocType (reader.Name,
492 reader ["PUBLIC"], reader ["SYSTEM"], reader.Value);
494 case XmlNodeType.SignificantWhitespace:
495 goto case XmlNodeType.Whitespace;
496 case XmlNodeType.Whitespace:
497 WriteWhitespace (reader.Value);
499 case XmlNodeType.EndElement:
500 WriteFullEndElement ();
502 case XmlNodeType.EndEntity:
504 case XmlNodeType.None:
505 break; // Do nothing, nor reporting errors.
507 throw new XmlException ("Unexpected node " + reader.Name + " of type " + reader.NodeType);
512 public abstract void WriteProcessingInstruction (string name, string text);
514 public abstract void WriteRaw (string data);
516 public abstract void WriteRaw (char[] buffer, int index, int count);
519 public void WriteStartAttribute (string localName)
521 WriteStartAttribute (null, localName, null);
525 public void WriteStartAttribute (string localName, string ns)
527 WriteStartAttribute (null, localName, ns);
530 public abstract void WriteStartAttribute (string prefix, string localName, string ns);
532 public abstract void WriteStartDocument ();
534 public abstract void WriteStartDocument (bool standalone);
536 public void WriteStartElement (string localName)
538 WriteStartElement (null, localName, null);
541 public void WriteStartElement (string localName, string ns)
543 WriteStartElement (null, localName, ns);
546 public abstract void WriteStartElement (string prefix, string localName, string ns);
548 public abstract void WriteString (string text);
550 public abstract void WriteSurrogateCharEntity (char lowChar, char highChar);
552 public abstract void WriteWhitespace (string ws);
556 public virtual void WriteValue (bool value)
558 WriteString (XQueryConvert.BooleanToString (value));
562 public virtual void WriteValue (DateTime value)
564 WriteString (XmlConvert.ToString (value));
568 public virtual void WriteValue (decimal value)
570 WriteString (XQueryConvert.DecimalToString (value));
574 public virtual void WriteValue (double value)
576 WriteString (XQueryConvert.DoubleToString (value));
580 public virtual void WriteValue (int value)
582 WriteString (XQueryConvert.IntToString (value));
586 public virtual void WriteValue (long value)
588 WriteString (XQueryConvert.IntegerToString (value));
592 public virtual void WriteValue (object value)
595 WriteString ((string) value);
596 else if (value is bool)
597 WriteValue ((bool) value);
598 else if (value is DateTime)
599 WriteValue ((DateTime) value);
600 else if (value is decimal)
601 WriteValue ((decimal) value);
602 else if (value is double)
603 WriteValue ((double) value);
604 else if (value is int)
605 WriteValue ((int) value);
606 else if (value is long)
607 WriteValue ((long) value);
608 else if (value is XmlQualifiedName) {
609 XmlQualifiedName qname = (XmlQualifiedName) value;
610 WriteQualifiedName (qname.Name, qname.Namespace);
613 throw new NotImplementedException ("Argument value is " + value);
617 public virtual void WriteValue (float value)
619 WriteString (XQueryConvert.FloatToString (value));
623 public virtual void WriteValue (string value)