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 ();
212 WriteNode (reader, defattr);
214 case XmlNodeType.Attribute:
215 case XmlNodeType.Text:
216 WriteTextNode (reader, defattr);
219 base.WriteNode (reader, defattr);
224 private void WriteAttribute (XmlDictionaryReader reader, bool defattr)
226 if (!defattr && reader.IsDefault)
229 WriteStartAttribute (reader.Prefix, reader.LocalName, reader.NamespaceURI);
231 // no ReadAttributeValue() in 2.1 profile.
232 WriteTextNode (reader, true);
234 while (reader.ReadAttributeValue ()) {
235 switch (reader.NodeType) {
236 case XmlNodeType.Text:
237 WriteTextNode (reader, true);
239 case XmlNodeType.EntityReference:
240 WriteEntityRef (reader.Name);
245 WriteEndAttribute ();
248 public override void WriteNode (XmlReader reader, bool defattr)
251 throw new ArgumentNullException ("reader");
253 XmlDictionaryReader dr = reader as XmlDictionaryReader;
255 WriteNode (dr, defattr);
257 base.WriteNode (reader, defattr);
260 public virtual void WriteQualifiedName (
261 XmlDictionaryString localName,
262 XmlDictionaryString namespaceUri)
264 WriteQualifiedName (localName.Value, namespaceUri.Value);
267 public void WriteStartAttribute (
268 XmlDictionaryString localName,
269 XmlDictionaryString namespaceUri)
271 WriteStartAttribute (localName.Value, namespaceUri.Value);
274 public virtual void WriteStartAttribute (string prefix,
275 XmlDictionaryString localName,
276 XmlDictionaryString namespaceUri)
278 WriteStartAttribute (prefix, localName.Value, namespaceUri.Value);
281 public void WriteStartElement (
282 XmlDictionaryString localName,
283 XmlDictionaryString namespaceUri)
285 WriteStartElement (null, localName, namespaceUri);
288 public virtual void WriteStartElement (string prefix,
289 XmlDictionaryString localName,
290 XmlDictionaryString namespaceUri)
292 if (localName == null)
293 throw new ArgumentException ("localName must not be null.", "localName");
294 WriteStartElement (prefix, localName.Value,
295 namespaceUri != null ? namespaceUri.Value : null);
298 public virtual void WriteString (XmlDictionaryString value)
300 WriteString (value.Value);
303 protected virtual void WriteTextNode (XmlDictionaryReader reader, bool isAttribute)
305 WriteString (reader.Value);
310 public virtual void WriteValue (Guid guid)
312 WriteString (guid.ToString ());
315 public virtual void WriteValue (IStreamProvider value)
318 throw new ArgumentNullException ("value");
320 Stream stream = value.GetStream ();
321 byte[] buf = new byte [Math.Min (2048, stream.CanSeek ? stream.Length : 2048)];
323 while ((read = stream.Read (buf, 0, buf.Length)) > 0) {
324 WriteBase64 (buf, 0, read);
326 value.ReleaseStream (stream);
329 public virtual void WriteValue (TimeSpan duration)
331 WriteString (XmlConvert.ToString (duration));
334 public virtual void WriteValue (UniqueId id)
337 throw new ArgumentNullException ("id");
338 WriteString (id.ToString ());
341 public virtual void WriteValue (XmlDictionaryString value)
343 WriteValue (value.Value);
346 public virtual void WriteXmlAttribute (string localName, string value)
348 WriteAttributeString ("xml", localName, "http://www.w3.org/XML/1998/namespace", value);
351 public virtual void WriteXmlAttribute (XmlDictionaryString localName,
352 XmlDictionaryString value)
354 WriteXmlAttribute (localName.Value, value.Value);
357 public virtual void WriteXmlnsAttribute (
358 string prefix, string namespaceUri)
360 // BTW .NET 2.0 those XmlWriters from XmlWrite.Create()
361 // rejects namespace overriding i.e.
363 // xw.WriteStartElement ("foo", "urn:foo");
364 // xw.WriteXmlnsAttribute ("foo", "urn:bar");
366 // causes an XmlException. We need fix in sys.xml.dll
368 // When the prefix is null, this writer must mock
369 // a dummy namespace up. It is then up to the actual
370 // writer how it is determined in the output. (When
371 // there is a duplicate, then it will be further
374 prefix = "d" + Depth + "p1";
376 if (prefix == String.Empty)
377 WriteAttributeString ("xmlns", namespaceUri);
379 WriteAttributeString ("xmlns", prefix, "http://www.w3.org/2000/xmlns/", namespaceUri);
382 public virtual void WriteXmlnsAttribute (string prefix,
383 XmlDictionaryString namespaceUri)
385 WriteXmlnsAttribute (prefix, namespaceUri.Value);