2 // XmlDictionaryWriter.cs
5 // Atsushi Enomoto <atsushi@ximian.com>
7 // Copyright (C) 2005 Novell, Inc. http://www.novell.com
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
35 public abstract partial class XmlDictionaryWriter : XmlWriter
37 static readonly Encoding utf8_unmarked = new UTF8Encoding (false);
41 protected XmlDictionaryWriter ()
47 set { depth = value; }
50 public virtual bool CanCanonicalize {
54 public static XmlDictionaryWriter CreateBinaryWriter (
57 return CreateBinaryWriter (stream, null, null, false);
60 public static XmlDictionaryWriter CreateBinaryWriter (
61 Stream stream, IXmlDictionary dictionary)
63 return CreateBinaryWriter (stream, dictionary, null, false);
66 public static XmlDictionaryWriter CreateBinaryWriter (
67 Stream stream, IXmlDictionary dictionary,
68 XmlBinaryWriterSession session)
70 return CreateBinaryWriter (stream, dictionary, session, false);
73 public static XmlDictionaryWriter CreateBinaryWriter (
74 Stream stream, IXmlDictionary dictionary,
75 XmlBinaryWriterSession session, bool ownsStream)
77 return new XmlBinaryDictionaryWriter (stream,
78 dictionary, session, ownsStream);
81 public static XmlDictionaryWriter CreateDictionaryWriter (XmlWriter writer)
83 return new XmlSimpleDictionaryWriter (writer);
86 public static XmlDictionaryWriter CreateMtomWriter (
87 Stream stream, Encoding encoding, int maxSizeInBytes,
90 return CreateMtomWriter (stream, encoding,
91 maxSizeInBytes, startInfo, Guid.NewGuid () + "id=1", "http://tempuri.org/0/" + DateTime.Now.Ticks, true, false);
94 public static XmlDictionaryWriter CreateMtomWriter (
95 Stream stream, Encoding encoding, int maxSizeInBytes,
96 string startInfo, string boundary, string startUri,
97 bool writeMessageHeaders, bool ownsStream)
99 return new XmlMtomDictionaryWriter (stream, encoding, maxSizeInBytes, startInfo, boundary, startUri, writeMessageHeaders, ownsStream);
102 public static XmlDictionaryWriter CreateTextWriter (
105 return CreateTextWriter (stream, Encoding.UTF8);
108 public static XmlDictionaryWriter CreateTextWriter (
109 Stream stream, Encoding encoding)
111 return CreateTextWriter (stream, encoding, false);
114 // BTW looks like it creates an instance of different
115 // implementation than those from XmlWriter.Create().
116 public static XmlDictionaryWriter CreateTextWriter (
117 Stream stream, Encoding encoding, bool ownsStream)
120 throw new ArgumentNullException ("stream");
121 if (encoding == null)
122 throw new ArgumentNullException ("encoding");
124 switch (encoding.CodePage) {
128 encoding = utf8_unmarked;
131 throw new XmlException (String.Format ("XML declaration is required for encoding code page {0} but this XmlWriter does not support XML declaration.", encoding.CodePage));
134 XmlWriterSettings s = new XmlWriterSettings ();
135 s.Encoding = encoding;
136 s.CloseOutput = ownsStream;
137 s.OmitXmlDeclaration = true;
138 return CreateDictionaryWriter (XmlWriter.Create (stream, s));
141 public virtual void EndCanonicalization ()
143 throw new NotSupportedException ();
146 public virtual void StartCanonicalization (
147 Stream stream, bool includeComments,
148 string [] inclusivePrefixes)
150 throw new NotSupportedException ();
153 public void WriteAttributeString (
154 XmlDictionaryString localName,
155 XmlDictionaryString namespaceUri,
158 WriteAttributeString (null, localName, namespaceUri, value);
161 public void WriteAttributeString (string prefix,
162 XmlDictionaryString localName,
163 XmlDictionaryString namespaceUri,
166 WriteStartAttribute (prefix, localName, namespaceUri);
168 WriteEndAttribute ();
171 public void WriteElementString (
172 XmlDictionaryString localName,
173 XmlDictionaryString namespaceUri,
176 WriteElementString (null, localName, namespaceUri, value);
179 public void WriteElementString (string prefix,
180 XmlDictionaryString localName,
181 XmlDictionaryString namespaceUri,
184 WriteStartElement (prefix, localName, namespaceUri);
189 [MonoTODO ("make use of dictionary reader optimization")]
190 public virtual void WriteNode (XmlDictionaryReader reader,
194 throw new ArgumentNullException ("reader");
196 switch (reader.NodeType) {
197 case XmlNodeType.Element:
198 // gratuitously copied from System.XML/System.Xml/XmlWriter.cs:WriteNode(XmlReader,bool)
199 // as there doesn't seem to be a way to hook into attribute writing w/o handling Element.
200 WriteStartElement (reader.Prefix, reader.LocalName, reader.NamespaceURI);
201 // Well, I found that MS.NET took this way, since
202 // there was a error-prone SgmlReader that fails
203 // MoveToNextAttribute().
204 if (reader.HasAttributes) {
205 for (int i = 0; i < reader.AttributeCount; i++) {
206 reader.MoveToAttribute (i);
207 WriteAttribute (reader, defattr);
209 reader.MoveToElement ();
211 if (reader.IsEmptyElement)
214 int depth = reader.Depth;
216 if (reader.NodeType != XmlNodeType.EndElement) {
218 WriteNode (reader, defattr);
219 } while (depth < reader.Depth);
221 WriteFullEndElement ();
225 case XmlNodeType.Attribute:
226 case XmlNodeType.Text:
227 WriteTextNode (reader, defattr);
230 base.WriteNode (reader, defattr);
235 private void WriteAttribute (XmlDictionaryReader reader, bool defattr)
237 if (!defattr && reader.IsDefault)
240 WriteStartAttribute (reader.Prefix, reader.LocalName, reader.NamespaceURI);
242 // no ReadAttributeValue() in 2.1 profile.
243 WriteTextNode (reader, true);
245 while (reader.ReadAttributeValue ()) {
246 switch (reader.NodeType) {
247 case XmlNodeType.Text:
248 WriteTextNode (reader, true);
250 case XmlNodeType.EntityReference:
251 WriteEntityRef (reader.Name);
256 WriteEndAttribute ();
259 public override void WriteNode (XmlReader reader, bool defattr)
262 throw new ArgumentNullException ("reader");
264 XmlDictionaryReader dr = reader as XmlDictionaryReader;
266 WriteNode (dr, defattr);
268 base.WriteNode (reader, defattr);
271 public virtual void WriteQualifiedName (
272 XmlDictionaryString localName,
273 XmlDictionaryString namespaceUri)
275 WriteQualifiedName (localName.Value, namespaceUri.Value);
278 public void WriteStartAttribute (
279 XmlDictionaryString localName,
280 XmlDictionaryString namespaceUri)
282 WriteStartAttribute (localName.Value, namespaceUri.Value);
285 public virtual void WriteStartAttribute (string prefix,
286 XmlDictionaryString localName,
287 XmlDictionaryString namespaceUri)
289 WriteStartAttribute (prefix, localName.Value, namespaceUri.Value);
292 public void WriteStartElement (
293 XmlDictionaryString localName,
294 XmlDictionaryString namespaceUri)
296 WriteStartElement (null, localName, namespaceUri);
299 public virtual void WriteStartElement (string prefix,
300 XmlDictionaryString localName,
301 XmlDictionaryString namespaceUri)
303 if (localName == null)
304 throw new ArgumentException ("localName must not be null.", "localName");
305 WriteStartElement (prefix, localName.Value,
306 namespaceUri != null ? namespaceUri.Value : null);
309 public virtual void WriteString (XmlDictionaryString value)
311 WriteString (value.Value);
314 protected virtual void WriteTextNode (XmlDictionaryReader reader, bool isAttribute)
316 WriteString (reader.Value);
321 public virtual void WriteValue (Guid guid)
323 WriteString (guid.ToString ());
326 public virtual void WriteValue (IStreamProvider value)
329 throw new ArgumentNullException ("value");
331 Stream stream = value.GetStream ();
332 byte[] buf = new byte [Math.Min (2048, stream.CanSeek ? stream.Length : 2048)];
334 while ((read = stream.Read (buf, 0, buf.Length)) > 0) {
335 WriteBase64 (buf, 0, read);
337 value.ReleaseStream (stream);
340 public virtual void WriteValue (TimeSpan duration)
342 WriteString (XmlConvert.ToString (duration));
345 public virtual void WriteValue (UniqueId id)
348 throw new ArgumentNullException ("id");
349 WriteString (id.ToString ());
352 public virtual void WriteValue (XmlDictionaryString value)
354 WriteValue (value.Value);
357 public virtual void WriteXmlAttribute (string localName, string value)
359 WriteAttributeString ("xml", localName, "http://www.w3.org/XML/1998/namespace", value);
362 public virtual void WriteXmlAttribute (XmlDictionaryString localName,
363 XmlDictionaryString value)
365 WriteXmlAttribute (localName.Value, value.Value);
368 public virtual void WriteXmlnsAttribute (
369 string prefix, string namespaceUri)
371 // BTW .NET 2.0 those XmlWriters from XmlWrite.Create()
372 // rejects namespace overriding i.e.
374 // xw.WriteStartElement ("foo", "urn:foo");
375 // xw.WriteXmlnsAttribute ("foo", "urn:bar");
377 // causes an XmlException. We need fix in sys.xml.dll
379 // When the prefix is null, this writer must mock
380 // a dummy namespace up. It is then up to the actual
381 // writer how it is determined in the output. (When
382 // there is a duplicate, then it will be further
385 prefix = "d" + Depth + "p1";
387 if (prefix == String.Empty)
388 WriteAttributeString ("xmlns", namespaceUri);
390 WriteAttributeString ("xmlns", prefix, "http://www.w3.org/2000/xmlns/", namespaceUri);
393 public virtual void WriteXmlnsAttribute (string prefix,
394 XmlDictionaryString namespaceUri)
396 WriteXmlnsAttribute (prefix, namespaceUri.Value);