// Source code for Part 5 of Bob Swart's series on Blogging with Delphi, ASP.NET and ECO

class
  procedure TRSSWebService.GenerateRSS(EcoSpace: Borland.Eco.Handles.EcoSpace;
  const Cat: String; const FileName: String);
var
  Feed: XmlTextWriter;
  OclService: IOclService;
  IdService: IExternalIdService;
  ResultElements: IElementCollection;
  Posts: Post;
  i,j,k: Integer;
  Summary: String;
  WeblogUrl: String;

begin
  WeblogUrl := ConfigurationSettings.AppSettings['URL'].ToString
  if FileName = '' then
    Feed := XmlTextWriter.Create(
      HttpContext.Current.Server.MapPath('\Weblog') + '\RSS\Weblog.xml', nil)
  else
    Feed := XmlTextWriter.Create(
      HttpContext.Current.Server.MapPath('\Weblog') +
        '\RSS\' + FileName + '.xml', nil);
  try
    Feed.Formatting := Formatting.None; // Indented;
    Feed.WriteStartDocument;
    Feed.WriteStartElement('', 'rss', ''); // prefix, name, ns
    Feed.WriteAttributeString('version', '2.0');
    Feed.WriteStartElement('', 'channel', '');

    Feed.WriteElementString('title', 'Dr.Bob''s Delphi Notes');
    Feed.WriteElementString('link', 'http://www.drbob42.com/blog');
    if Cat <> '' then Feed.WriteElementString('category', Cat);
    Feed.WriteElementString('description', '...');
    Feed.WriteElementString('language', 'en-us');
    Feed.WriteElementString('managingEditor', 'b.swart@chello.nl (Bob Swart)');
    Feed.WriteElementString('webMaster', 'b.swart@chello.nl (Bob Swart)');
    Summary := DateTime.Now.ToString('ddd, dd MMM yyyy HH:mm:ss zz')+'00';
    Feed.WriteElementString('pubDate', Summary);
    Feed.WriteElementString('lastBuildDate', Summary);
    Feed.WriteElementString('generator', 'eBob42RSS v0.90');
    Feed.WriteElementString('docs', 'http://blogs.law.harvard.edu/tech/rss');
    Feed.WriteStartElement('', 'image', '');
      Feed.WriteElementString('title', 'Dr.Bob''s Delphi Notes');
      Feed.WriteElementString('link', 'http://www.drbob42.com/blog');
      Feed.WriteElementString('url', 'http://www.drbob42.com/gif/eBob42.gif');
      Feed.WriteElementString('width', '118');
      Feed.WriteElementString('height', '78');
    Feed.WriteEndElement;

    IdService := EcoSpace.GetEcoService(typeof(IExternalIdService))
      as IExternalIdService;
    OclService := EcoSpace.GetEcoService(typeof(IOclService)) as IOclService;
    if Cat = '' then
      ResultElements :=
        OclService.Evaluate('Post.allInstances->orderdescending(Posted)').
          GetAsCollection
    else
      ResultElements :=
        OclService.Evaluate('Category->allInstances->select(c | c.Name = ''' +
          Cat + ''').Posts->orderdescending(Posted)').GetAsCollection;

    for i:=0 to ResultElements.Count-1 do
    begin
      Posts := (ResultElements[i].AsObject as Post);
      Feed.WriteStartElement('', 'item', '');
      Feed.WriteElementString('title', Posts.Title);
      Feed.WriteElementString('link', WeblogUrl +
        IdService.IdForObject(Posts.AsIObject));
      Feed.WriteElementString('author',  'b.swart@chello.nl (' +
        Posts.Author + ')');
      if Cat = '' then // list categories
      begin
        Summary := '';
        for j:=0 to Posts.Categories.Count-1 do
          Summary := Summary + Posts.Categories[j].Name + ', ';
        if Summary <> '' then Delete(Summary,Length(Summary)-1,2);
        Feed.WriteElementString('category', Summary)
      end;
      Summary := Posts.Summary;
      if Summary = '' then
      begin
        j := Pos('. ',Posts.Contents);
        if j = 0 then j := Pos('.'#13,Posts.Contents);
        if j = 0 then j := Pos('.'#10,Posts.Contents);
        if j > 0 then
          Summary := Copy(Posts.Contents,1,j)
        else
          Summary := Posts.Title
      end;
      repeat
        j := Pos('{',Summary);
        if j >= 0 then
          k := Pos('}',Summary)
        else k := -1;
        if k > j then Delete(Summary,j,k-j+1)
      until (k <= j);
      Feed.WriteElementString('description', Summary);
      Feed.WriteElementString('pubDate',
        Posts.Posted.ToString('ddd, dd MMM yyyy HH:mm:ss zz')+'00');
      Feed.WriteEndElement // item
    end;
    Feed.WriteEndElement; // channel
    Feed.WriteEndElement; // rss
  finally
    Feed.WriteEndDocument;
    Feed.Flush;
    Feed.Close;
    Feed.Free
  end

end;