~ubuntu-branches/ubuntu/saucy/blam/saucy

« back to all changes in this revision

Viewing changes to src/rss/RssWriter.cs

  • Committer: Bazaar Package Importer
  • Author(s): Barry deFreese
  • Date: 2005-09-27 21:38:56 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20050927213856-8no09ppptvhpqqsh
Tags: 1.8.2-2ubuntu6
Change .desktop comment description

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* RssWriter.cs
2
 
 * ============
3
 
 * 
4
 
 * RSS.NET (http://rss-net.sf.net/)
5
 
 * Copyright � 2002, 2003 George Tsiokos. All Rights Reserved.
6
 
 * 
7
 
 * RSS 2.0 (http://blogs.law.harvard.edu/tech/rss)
8
 
 * RSS 2.0 is offered by the Berkman Center for Internet & Society at 
9
 
 * Harvard Law School under the terms of the Attribution/Share Alike 
10
 
 * Creative Commons license.
11
 
 * 
12
 
 * Permission is hereby granted, free of charge, to any person obtaining 
13
 
 * a copy of this software and associated documentation files (the "Software"), 
14
 
 * to deal in the Software without restriction, including without limitation 
15
 
 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 
16
 
 * and/or sell copies of the Software, and to permit persons to whom the 
17
 
 * Software is furnished to do so, subject to the following conditions:
18
 
 * 
19
 
 * The above copyright notice and this permission notice shall be included in all
20
 
 * copies or substantial portions of the Software.
21
 
 * 
22
 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
23
 
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
24
 
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 
25
 
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
26
 
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 
27
 
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 
28
 
 * THE SOFTWARE.
29
 
*/
30
 
using System;
31
 
using System.Xml;
32
 
using System.Text;
33
 
using System.IO;
34
 
 
35
 
namespace Rss
36
 
{
37
 
        /// <summary>Writes an RSS XML file.</summary>
38
 
        /// <remarks>Represents a writer that provides a fast, non-cached, forward-only way of generating streams or files containing RSS XML data that conforms to the W3C Extensible Markup Language (XML) 1.0 and the Namespaces in XML recommendations.</remarks>
39
 
        public class RssWriter
40
 
        {
41
 
                private XmlTextWriter writer = null;
42
 
                
43
 
                // functional var
44
 
                private bool wroteStartDocument = false;
45
 
                private bool wroteChannel = false;
46
 
 
47
 
                // prefrences
48
 
                private RssVersion rssVersion = RssVersion.RSS20;
49
 
                private Formatting xmlFormat = Formatting.Indented;
50
 
                private int xmlIndentation = 2;
51
 
 
52
 
                // constants
53
 
                private const string DateTimeFormatString = "ddd, dd MMM yyyy HH':'mm':'ss 'GMT'";
54
 
 
55
 
                // modules
56
 
                private RssModuleCollection _rssModules = new RssModuleCollection();
57
 
 
58
 
                #region Constructors
59
 
 
60
 
                /// <summary>Creates an instance of the RssWriter class using the specified TextWriter.</summary>
61
 
                /// <param name="textWriter">specified TextWriter</param>
62
 
                public RssWriter(TextWriter textWriter)
63
 
                {
64
 
                        writer = new XmlTextWriter(textWriter);
65
 
                }
66
 
 
67
 
                /// <summary>Creates an instance of the RssWriter class using the specified Stream and Encoding.</summary>
68
 
                /// <exception cref="ArgumentException">The encoding is not supported or the stream cannot be written to.</exception>
69
 
                /// <param name="stream">Stream to output to</param>
70
 
                /// <param name="encoding">The encoding to use. If encoding is (null c#, Nothing vb) it writes out the stream as UTF-8.</param>
71
 
                public RssWriter(Stream stream, Encoding encoding)
72
 
                {
73
 
                        writer = new XmlTextWriter(stream, encoding);
74
 
                }
75
 
 
76
 
                /// <summary>Creates an instance of the RssWriter class using the specified Stream.</summary>
77
 
                /// <remarks>The encoding is ISO-8859-1.</remarks>
78
 
                /// <exception cref="ArgumentException">The Stream cannot be written to.</exception>
79
 
                /// <param name="stream">specified Stream</param>
80
 
                public RssWriter(Stream stream)
81
 
                {
82
 
                        writer = new XmlTextWriter(stream, System.Text.Encoding.GetEncoding("ISO-8859-1"));
83
 
                }
84
 
 
85
 
                /// <summary>Creates an instance of the RssWriter class using the specified file and Encoding.</summary>
86
 
                /// <exception cref="ArgumentException">The encoding is not supported; the filename is empty, contains only white space, or contains one or more invalid characters.</exception>
87
 
                /// <exception cref="UnauthorizedAccessException">Access is denied.</exception>
88
 
                /// <exception cref="ArgumentNullException">The filename is a (null c#, Nothing vb) reference.</exception>
89
 
                /// <exception cref="DirectoryNotFoundException">The directory to write to is not found.</exception>
90
 
                /// <exception cref="IOException">The filename includes an incorrect or invalid syntax for file name, directory name, or volume label syntax.</exception>
91
 
                /// <exception cref="System.Security.SecurityException">The caller does not have the required permission.</exception>
92
 
                /// <param name="fileName">specified file (including path) If the file exists, it will be truncated with the new content.</param>
93
 
                /// <param name="encoding">specified Encoding</param>
94
 
                public RssWriter(string fileName, Encoding encoding)
95
 
                {
96
 
                        writer = new XmlTextWriter(fileName, encoding);
97
 
                }
98
 
 
99
 
                /// <summary>Creates an instance of the RssWriter class using the specified file.</summary>
100
 
                /// <remarks>The encoding is ISO-8859-1.</remarks>
101
 
                /// <exception cref="ArgumentException">The filename is empty, contains only white space, or contains one or more invalid characters.</exception>
102
 
                /// <exception cref="UnauthorizedAccessException">Access is denied.</exception>
103
 
                /// <exception cref="ArgumentNullException">The filename is a (null c#, Nothing vb) reference.</exception>
104
 
                /// <exception cref="DirectoryNotFoundException">The directory to write to is not found.</exception>
105
 
                /// <exception cref="IOException">The filename includes an incorrect or invalid syntax for file name, directory name, or volume label syntax.</exception>
106
 
                /// <exception cref="System.Security.SecurityException">The caller does not have the required permission.</exception>
107
 
                /// <param name="fileName">specified file (including path) If the file exists, it will be truncated with the new content.</param>
108
 
                public RssWriter(string fileName)
109
 
                {
110
 
                        writer = new XmlTextWriter(fileName, System.Text.Encoding.GetEncoding("ISO-8859-1"));
111
 
                }
112
 
                #endregion
113
 
 
114
 
                /// <summary>Writes the begining data to the RSS file</summary>
115
 
                /// <remarks>This routine is called from the WriteChannel and WriteItem subs</remarks>
116
 
                /// <exception cref="NotSupportedException">RDF Site Summary (RSS) 1.0 is not currently supported.</exception>
117
 
                private void BeginDocument()
118
 
                {
119
 
                        if (!wroteStartDocument)
120
 
                        {
121
 
                                if (rssVersion == RssVersion.Empty)
122
 
                                        rssVersion = RssVersion.RSS20;
123
 
                                writer.Formatting = xmlFormat;
124
 
                                writer.Indentation = xmlIndentation;
125
 
                                writer.WriteStartDocument();
126
 
                                if (rssVersion != RssVersion.RSS20)
127
 
                                        writer.WriteComment("Generated by RSS.NET: http://rss-net.sf.net");
128
 
 
129
 
                                //exc: The xml:space or xml:lang attribute value is invalid.
130
 
                                switch (rssVersion)
131
 
                                {
132
 
                                        case RssVersion.RSS090:
133
 
                                                //<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://my.netscape.com/rdf/simple/0.9/">
134
 
                                                writer.WriteStartElement("RDF", "rdf", "http://www.w3.org/1999/02/22-rdf-syntax-ns#");                                          
135
 
                                                break;
136
 
                                        case RssVersion.RSS091:
137
 
                                                writer.WriteStartElement("rss");
138
 
                                                writer.WriteDocType("rss", "-//Netscape Communications//DTD RSS 0.91//EN", "http://my.netscape.com/publish/formats/rss-0.91.dtd", null);
139
 
                                                writer.WriteAttributeString("version", "0.91");
140
 
                                                break;
141
 
                                        case RssVersion.RSS092:
142
 
                                                writer.WriteStartElement("rss");
143
 
                                                writer.WriteAttributeString("version", "0.92");
144
 
                                                break;
145
 
                                        case RssVersion.RSS10:
146
 
                                                throw new NotSupportedException("RDF Site Summary (RSS) 1.0 is not currently supported.");
147
 
                                        case RssVersion.RSS20:
148
 
                                                writer.WriteStartElement("rss");
149
 
                                                writer.WriteAttributeString("version", "2.0");
150
 
                                                // RSS Modules
151
 
                                                foreach(RssModule rssModule in this._rssModules)
152
 
                                                {
153
 
                                                        WriteAttribute("xmlns:" + rssModule.NamespacePrefix, rssModule.NamespaceURL.ToString(), true);
154
 
                                                }
155
 
                                                break;
156
 
                                }
157
 
                                wroteStartDocument = true;
158
 
                        }
159
 
                }
160
 
                private void writeChannel(RssChannel channel)
161
 
                {
162
 
                        if (writer == null)
163
 
                                throw new InvalidOperationException("RssWriter has been closed, and can not be written to.");
164
 
                        if (channel == null)
165
 
                                throw new ArgumentNullException("Channel must be instanciated with data to be written.");
166
 
                        
167
 
                        if (wroteChannel)
168
 
                                writer.WriteEndElement();
169
 
                        else
170
 
                                wroteChannel = true;
171
 
 
172
 
                        BeginDocument();
173
 
 
174
 
                        writer.WriteStartElement("channel");
175
 
                        WriteElement("title", channel.Title, true);
176
 
                        WriteElement("description", channel.Description, true);
177
 
                        WriteElement("link", channel.Link, true);
178
 
                        if (channel.Image != null)
179
 
                        {
180
 
                                writer.WriteStartElement("image");
181
 
                                WriteElement("title", channel.Image.Title, true);
182
 
                                WriteElement("url", channel.Image.Url, true);
183
 
                                WriteElement("link", channel.Image.Link, true);
184
 
                                switch (rssVersion)
185
 
                                {
186
 
                                        case RssVersion.RSS091:
187
 
                                        case RssVersion.RSS092:
188
 
                                        case RssVersion.RSS20:
189
 
                                                WriteElement("description", channel.Image.Description, false);
190
 
                                                WriteElement("width", channel.Image.Width, false);
191
 
                                                WriteElement("height", channel.Image.Height, false);
192
 
                                                break;
193
 
                                }
194
 
                                writer.WriteEndElement();
195
 
                        }
196
 
                        switch (rssVersion)
197
 
                        {
198
 
                                case RssVersion.RSS091:
199
 
                                case RssVersion.RSS092:
200
 
                                case RssVersion.RSS20:
201
 
                                        WriteElement("language", channel.Language, rssVersion == RssVersion.RSS091);
202
 
                                        WriteElement("copyright", channel.Copyright, false);
203
 
                                        WriteElement("managingEditor", channel.ManagingEditor, false);
204
 
                                        WriteElement("webMaster", channel.WebMaster, false);
205
 
                                        WriteElement("pubDate", channel.PubDate, false);
206
 
                                        WriteElement("lastBuildDate", channel.LastBuildDate, false);
207
 
                                        if (channel.Docs != RssDefault.String)
208
 
                                                WriteElement("docs", channel.Docs, false);
209
 
                                        else
210
 
                                                switch (rssVersion)
211
 
                                                {
212
 
                                                        case RssVersion.RSS091:
213
 
                                                                WriteElement("docs", "http://my.netscape.com/publish/formats/rss-spec-0.91.html", false);
214
 
                                                                break;
215
 
                                                        case RssVersion.RSS092:
216
 
                                                                WriteElement("docs", "http://backend.userland.com/rss092", false);
217
 
                                                                break;
218
 
                                                        case RssVersion.RSS20:
219
 
                                                                WriteElement("docs", "http://backend.userland.com/rss", false);
220
 
                                                                break;
221
 
                                                }
222
 
                                        WriteElement("rating", channel.Rating, false);
223
 
                                        string[] Days = {"monday","tuesday","wednesday","thursday","friday","saturday","sunday"};
224
 
                                        for (int i = 0; i <= 6; i++)
225
 
                                                if (channel.SkipDays[i])
226
 
                                                {
227
 
                                                        writer.WriteStartElement("skipDays");
228
 
                                                        for (int i2 = 0; i2 <= 6; i2++)
229
 
                                                                if (channel.SkipDays[i2])
230
 
                                                                        WriteElement("day", Days[i2], false);
231
 
                                                        writer.WriteEndElement();
232
 
                                                        break;
233
 
                                                }
234
 
                                        for (int i = 0; i <= 23; i++)
235
 
                                                if (channel.SkipHours[i])
236
 
                                                {
237
 
                                                        writer.WriteStartElement("skipHours");
238
 
                                                        for (int i2 = 0; i2<= 23; i2++)
239
 
                                                                if (channel.SkipHours[i2])
240
 
                                                                        WriteElement("hour", i2+1, false);
241
 
                                                        writer.WriteEndElement();
242
 
                                                        break;
243
 
                                                }
244
 
                                        break;
245
 
                        }
246
 
                        switch (rssVersion)
247
 
                        {
248
 
                                case RssVersion.RSS092:
249
 
                                case RssVersion.RSS20:
250
 
                                        if (channel.Categories != null)
251
 
                                                foreach(RssCategory category in channel.Categories)
252
 
                                                        if (category.Name != RssDefault.String)
253
 
                                                        {
254
 
                                                                writer.WriteStartElement("category");
255
 
                                                                WriteAttribute("domain", category.Domain, false);
256
 
                                                                writer.WriteString(category.Name);
257
 
                                                                writer.WriteEndElement();
258
 
                                                        }
259
 
                                        if (channel.Cloud != null)
260
 
                                        {
261
 
                                                writer.WriteStartElement("cloud");
262
 
                                                WriteElement("domain", channel.Cloud.Domain, false);
263
 
                                                WriteElement("port", channel.Cloud.Port, false);
264
 
                                                WriteElement("path", channel.Cloud.Path, false);
265
 
                                                WriteElement("registerProcedure", channel.Cloud.RegisterProcedure, false);
266
 
                                                if (channel.Cloud.Protocol != RssCloudProtocol.Empty)
267
 
                                                        WriteElement("Protocol", channel.Cloud.Protocol, false);
268
 
                                                writer.WriteEndElement();
269
 
                                        }
270
 
                                        break;
271
 
                        }
272
 
                        if (rssVersion == RssVersion.RSS20)
273
 
                        {
274
 
                                if (channel.Generator != RssDefault.String)
275
 
                                        WriteElement("generator", channel.Generator, false);
276
 
                                else
277
 
                                        WriteElement("generator", "RSS.NET: http://www.rssdotnet.com/", false);
278
 
                                WriteElement("ttl", channel.TimeToLive, false);
279
 
 
280
 
                                // RSS Modules
281
 
                                foreach(RssModule rssModule in this._rssModules)
282
 
                                {
283
 
                                        if(rssModule.IsBoundTo(channel.GetHashCode()))
284
 
                                        {
285
 
                                                foreach(RssModuleItem rssModuleItem in rssModule.ChannelExtensions)
286
 
                                                {
287
 
                                                        if(rssModuleItem.SubElements.Count == 0)
288
 
                                                                WriteElement(rssModule.NamespacePrefix + ":" + rssModuleItem.Name, rssModuleItem.Text, rssModuleItem.IsRequired);
289
 
                                                        else
290
 
                                                                writeSubElements(rssModuleItem.SubElements, rssModule.NamespacePrefix);
291
 
                                                }
292
 
                                        }
293
 
                                }
294
 
                        }
295
 
                        if (channel.TextInput != null)
296
 
                        {
297
 
                                writer.WriteStartElement("textinput");
298
 
                                WriteElement("title", channel.TextInput.Title, true);
299
 
                                WriteElement("description", channel.TextInput.Description, true);
300
 
                                WriteElement("name", channel.TextInput.Name, true);
301
 
                                WriteElement("link", channel.TextInput.Link, true);
302
 
                                writer.WriteEndElement();
303
 
                        }
304
 
                        foreach (RssItem item in channel.Items)
305
 
                        {
306
 
                                writeItem(item, channel.GetHashCode());
307
 
                        }
308
 
                        writer.Flush();
309
 
                }
310
 
                private void writeItem(RssItem item, int channelHashCode)
311
 
                {
312
 
                        if (writer == null)
313
 
                                throw new InvalidOperationException("RssWriter has been closed, and can not be written to.");
314
 
                        if (item == null)
315
 
                                throw new ArgumentNullException("Item must be instanciated with data to be written.");
316
 
                        if (!wroteChannel)
317
 
                                throw new InvalidOperationException("Channel must be written first, before writing an item.");
318
 
 
319
 
                        BeginDocument();
320
 
 
321
 
                        writer.WriteStartElement("item");
322
 
                        switch (rssVersion)
323
 
                        {
324
 
                                case RssVersion.RSS090:
325
 
                                case RssVersion.RSS10:
326
 
                                case RssVersion.RSS091:
327
 
                                        WriteElement("title", item.Title, true);
328
 
                                        WriteElement("description", item.Description, false);
329
 
                                        WriteElement("link", item.Link, true);
330
 
                                        break;
331
 
                                case RssVersion.RSS20:
332
 
                                        if ((item.Title == RssDefault.String) && (item.Description == RssDefault.String))
333
 
                                                throw new ArgumentException("item title and description cannot be null");
334
 
                                        goto case RssVersion.RSS092;
335
 
                                case RssVersion.RSS092:
336
 
                                        WriteElement("title", item.Title, false);
337
 
                                        WriteElement("description", item.Description, false);
338
 
                                        WriteElement("link", item.Link, false);
339
 
                                        if (item.Source != null)
340
 
                                        {
341
 
                                                writer.WriteStartElement("source");
342
 
                                                WriteAttribute("url", item.Source.Url, true);
343
 
                                                writer.WriteString(item.Source.Name);
344
 
                                                writer.WriteEndElement();
345
 
                                        }
346
 
                                        if (item.Enclosure != null)
347
 
                                        {
348
 
                                                writer.WriteStartElement("enclosure");
349
 
                                                WriteAttribute("url", item.Enclosure.Url, true);
350
 
                                                WriteAttribute("length", item.Enclosure.Length, true);
351
 
                                                WriteAttribute("type", item.Enclosure.Type, true);
352
 
                                                writer.WriteEndElement();
353
 
                                        }
354
 
                                        foreach(RssCategory category in item.Categories)
355
 
                                                if (category.Name != RssDefault.String)
356
 
                                                {
357
 
                                                        writer.WriteStartElement("category");
358
 
                                                        WriteAttribute("domain", category.Domain, false);
359
 
                                                        writer.WriteString(category.Name);
360
 
                                                        writer.WriteEndElement();
361
 
                                                }
362
 
                                        break;
363
 
                        }
364
 
                        if (rssVersion == RssVersion.RSS20)
365
 
                        {
366
 
                                WriteElement("author", item.Author, false);
367
 
                                WriteElement("comments", item.Comments, false);
368
 
                                if ((item.Guid != null) && (item.Guid.Name != RssDefault.String))
369
 
                                {
370
 
                                        writer.WriteStartElement("guid");
371
 
                                        WriteAttribute("isPermaLink", (bool)item.Guid.PermaLink, false);
372
 
                                        writer.WriteString(item.Guid.Name);
373
 
                                        writer.WriteEndElement();
374
 
                                }
375
 
                                WriteElement("pubDate", item.PubDate, false);
376
 
 
377
 
                                foreach(RssModule rssModule in this._rssModules)
378
 
                                {
379
 
                                        if(rssModule.IsBoundTo(channelHashCode))
380
 
                                        {
381
 
                                                foreach(RssModuleItemCollection rssModuleItemCollection in rssModule.ItemExtensions)
382
 
                                                {
383
 
                                                        if(rssModuleItemCollection.IsBoundTo(item.GetHashCode()))
384
 
                                                                writeSubElements(rssModuleItemCollection, rssModule.NamespacePrefix);
385
 
                                                }
386
 
                                        }
387
 
                                }
388
 
                        }
389
 
                        writer.WriteEndElement();
390
 
                        writer.Flush();
391
 
                }
392
 
                /// <summary>Closes instance of RssWriter.</summary>
393
 
                /// <remarks>Writes end elements, and releases connections</remarks>
394
 
                /// <exception cref="InvalidOperationException">Occurs if the RssWriter is already closed or the caller is attempting to close before writing a channel.</exception>
395
 
                public void Close()
396
 
                {
397
 
                        if (writer == null)
398
 
                                throw new InvalidOperationException("RssWriter has been closed, and can not be closed again.");
399
 
                        
400
 
                        if (!wroteChannel)
401
 
                                throw new InvalidOperationException("Can't close RssWriter without first writing a channel.");
402
 
                        else
403
 
                                writer.WriteEndElement(); // </channel>
404
 
 
405
 
                        writer.WriteEndElement(); // </rss> or </rdf>
406
 
                        writer.Close();
407
 
                        writer = null;
408
 
                }
409
 
                /// <summary>Gets or sets the RSS version to write.</summary>
410
 
                /// <exception cref="InvalidOperationException">Can't change version number after data has been written.</exception>
411
 
                public RssVersion Version
412
 
                {
413
 
                        get { return rssVersion; }
414
 
                        set
415
 
                        {
416
 
                                if(wroteStartDocument)
417
 
                                        throw new InvalidOperationException("Can't change version number after data has been written.");
418
 
                                else
419
 
                                        rssVersion = value;
420
 
                        }
421
 
                }
422
 
                /// <summary>Gets or sets the <see cref="System.Xml.Formatting"/> of the XML output.</summary>
423
 
                /// <exception cref="InvalidOperationException">Can't change XML formatting after data has been written.</exception>
424
 
                public Formatting XmlFormat
425
 
                {
426
 
                        get { return xmlFormat; }
427
 
                        set
428
 
                        {
429
 
                                if(wroteStartDocument)
430
 
                                        throw new InvalidOperationException("Can't change XML formatting after data has been written.");
431
 
                                else
432
 
                                        xmlFormat = value;
433
 
                        }
434
 
                }
435
 
                /// <summary>Gets or sets how indentation to write for each level in the hierarchy when XmlFormat is set to <see cref="Formatting.Indented"/></summary>
436
 
                /// <exception cref="InvalidOperationException">Can't change XML formatting after data has been written.</exception>
437
 
                /// <exception cref="ArgumentException">Setting this property to a negative value.</exception>
438
 
                public int XmlIndentation
439
 
                {
440
 
                        get { return xmlIndentation; }
441
 
                        set
442
 
                        {
443
 
                                if(wroteStartDocument)
444
 
                                        throw new InvalidOperationException("Can't change XML indentation after data has been written.");
445
 
                                else
446
 
                                        if (value < 0)
447
 
                                                throw new ArgumentException("Setting this property to a negative value.");
448
 
                                        else
449
 
                                                xmlIndentation = value;
450
 
                        }
451
 
                }
452
 
                /// <summary>Writes an RSS channel</summary>
453
 
                /// <exception cref="InvalidOperationException">RssWriter has been closed, and can not be written to.</exception>
454
 
                /// <exception cref="ArgumentNullException">Channel must be instanciated with data, before calling Write.</exception>
455
 
                /// <param name="channel">RSS channel to write</param>
456
 
                public void Write(RssChannel channel)
457
 
                {
458
 
                        writeChannel(channel);
459
 
                }
460
 
                /// <summary>Writes an RSS item</summary>
461
 
                /// <exception cref="InvalidOperationException">Either the RssWriter has already been closed, or the caller is attempting to write an RSS item before an RSS channel.</exception>
462
 
                /// <exception cref="ArgumentNullException">Item must be instanciated with data, before calling Write.</exception>
463
 
                /// <param name="item">RSS item to write</param>
464
 
                public void Write(RssItem item)
465
 
                {
466
 
                        // NOTE: Standalone items cannot adhere to modules, hence -1 is passed. This may not be the case, however, no examples have been seen where this is legal.
467
 
                        writeItem(item, -1);
468
 
                }
469
 
 
470
 
                /// <summary>RSS modules</summary>
471
 
                public RssModuleCollection Modules
472
 
                {
473
 
                        get { return this._rssModules; }
474
 
                        set { this._rssModules = value; }
475
 
                }
476
 
                #region WriteElement
477
 
                /// <summary>Writes an element with the specified local name and value</summary>
478
 
                /// <param name="localName">the localname of the element</param>
479
 
                /// <param name="input">the value of the element</param>
480
 
                /// <param name="required">boolean that determines if input cannot be null</param>
481
 
                private void WriteElement(string localName, DateTime input, bool required)
482
 
                {
483
 
                        if (input != RssDefault.DateTime)
484
 
                                writer.WriteElementString(localName, XmlConvert.ToString(input,DateTimeFormatString));
485
 
                        else if (required)
486
 
                                        throw new ArgumentException(localName + " can not be null.");
487
 
                }
488
 
                /// <summary>Writes an element with the specified local name and value</summary>
489
 
                /// <param name="localName">the localname of the element</param>
490
 
                /// <param name="input">the value of the element</param>
491
 
                /// <param name="required">boolean that determines if input cannot be null</param>
492
 
                private void WriteElement(string localName, int input, bool required)
493
 
                {
494
 
                        if (input != RssDefault.Int)
495
 
                                writer.WriteElementString(localName, XmlConvert.ToString(input));
496
 
                        else if (required)
497
 
                                throw new ArgumentException(localName + " can not be null.");
498
 
                }
499
 
                /// <summary>Writes an element with the specified local name and value</summary>
500
 
                /// <param name="localName">the localname of the element</param>
501
 
                /// <param name="input">the value of the element</param>
502
 
                /// <param name="required">boolean that determines if input cannot be null</param>
503
 
                private void WriteElement(string localName, string input, bool required)
504
 
                {
505
 
                        if (input != RssDefault.String)
506
 
                                writer.WriteElementString(localName, input);
507
 
                        else if (required)
508
 
                                throw new ArgumentException(localName + " can not be null.");
509
 
                }
510
 
                /// <summary>Writes an element with the specified local name and value</summary>
511
 
                /// <param name="localName">the localname of the element</param>
512
 
                /// <param name="input">the value of the element</param>
513
 
                /// <param name="required">boolean that determines if input cannot be null</param>
514
 
                private void WriteElement(string localName, Uri input, bool required)
515
 
                {
516
 
                        if (input != RssDefault.Uri)
517
 
                                writer.WriteElementString(localName, input.ToString());
518
 
                        else if (required)
519
 
                                throw new ArgumentException(localName + " can not be null.");
520
 
                }
521
 
                /// <summary>Writes an element with the specified local name and value</summary>
522
 
                /// <param name="localName">the localname of the element</param>
523
 
                /// <param name="input">the value of the element</param>
524
 
                /// <param name="required">boolean that determines if input cannot be null</param>
525
 
                private void WriteElement(string localName, object input, bool required)
526
 
                {
527
 
                        if (input != null)
528
 
                                writer.WriteElementString(localName, input.ToString());
529
 
                        else if (required)
530
 
                                throw new ArgumentException(localName + " can not be null.");
531
 
                }
532
 
                #endregion
533
 
                #region WriteAttribute
534
 
                /// <summary>Writes an attribute with the specified local name and value</summary>
535
 
                /// <param name="localName">the localname of the element</param>
536
 
                /// <param name="input">the value of the element</param>
537
 
                /// <param name="required">boolean that determines if input cannot be null</param>
538
 
                private void WriteAttribute(string localName, DateTime input, bool required)
539
 
                {
540
 
                        if (input != RssDefault.DateTime)
541
 
                                writer.WriteAttributeString(localName, XmlConvert.ToString(input,DateTimeFormatString));
542
 
                        else if (required)
543
 
                                throw new ArgumentException(localName + " can not be null.");
544
 
                }
545
 
                /// <summary>Writes an attribute with the specified local name and value</summary>
546
 
                /// <param name="localName">the localname of the element</param>
547
 
                /// <param name="input">the value of the element</param>
548
 
                /// <param name="required">boolean that determines if input cannot be null</param>
549
 
                private void WriteAttribute(string localName, int input, bool required)
550
 
                {
551
 
                        if (input != RssDefault.Int)
552
 
                                writer.WriteAttributeString(localName, XmlConvert.ToString(input));
553
 
                        else if (required)
554
 
                                throw new ArgumentException(localName + " can not be null.");
555
 
                }
556
 
                /// <summary>Writes an attribute with the specified local name and value</summary>
557
 
                /// <param name="localName">the localname of the element</param>
558
 
                /// <param name="input">the value of the element</param>
559
 
                /// <param name="required">boolean that determines if input cannot be null</param>
560
 
                private void WriteAttribute(string localName, string input, bool required)
561
 
                {
562
 
                        if (input != RssDefault.String)
563
 
                                writer.WriteAttributeString(localName, input);
564
 
                        else if (required)
565
 
                                throw new ArgumentException(localName + " can not be null.");
566
 
                }
567
 
                /// <summary>Writes an attribute with the specified local name and value</summary>
568
 
                /// <param name="localName">the localname of the element</param>
569
 
                /// <param name="input">the value of the element</param>
570
 
                /// <param name="required">boolean that determines if input cannot be null</param>
571
 
                private void WriteAttribute(string localName, Uri input, bool required)
572
 
                {
573
 
                        if (input != RssDefault.Uri)
574
 
                                writer.WriteAttributeString(localName, input.ToString());
575
 
                        else if (required)
576
 
                                throw new ArgumentException(localName + " can not be null.");
577
 
                }
578
 
                /// <summary>Writes an attribute with the specified local name and value</summary>
579
 
                /// <param name="localName">the localname of the element</param>
580
 
                /// <param name="input">the value of the element</param>
581
 
                /// <param name="required">boolean that determines if input cannot be null</param>
582
 
                private void WriteAttribute(string localName, object input, bool required)
583
 
                {
584
 
                        if (input != null)
585
 
                                writer.WriteAttributeString(localName, input.ToString());
586
 
                        else if (required)
587
 
                                throw new ArgumentException(localName + " can not be null.");
588
 
                }
589
 
                #endregion
590
 
                #region WriteSubElements
591
 
                private void writeSubElements(RssModuleItemCollection items, string NamespacePrefix)
592
 
                {
593
 
                        foreach(RssModuleItem rssModuleItem in items)
594
 
                        {
595
 
                                if(rssModuleItem.SubElements.Count == 0)
596
 
                                        WriteElement(NamespacePrefix + ":" + rssModuleItem.Name, rssModuleItem.Text, rssModuleItem.IsRequired);
597
 
                                else
598
 
                                {
599
 
                                        writer.WriteStartElement(NamespacePrefix + ":" + rssModuleItem.Name);
600
 
                                        writeSubElements(rssModuleItem.SubElements, NamespacePrefix);
601
 
                                        writer.WriteEndElement();
602
 
                                }
603
 
                        }
604
 
                }
605
 
                #endregion
606
 
        }
607
 
}