]> err.no Git - sope/blob - sope-xml/samples/rss2plist2.m
5bff621752ba0a55745d73d195254c9080c427b0
[sope] / sope-xml / samples / rss2plist2.m
1 /*
2   Copyright (C) 2000-2003 SKYRIX Software AG
3
4   This file is part of OGo
5
6   OGo is free software; you can redistribute it and/or modify it under
7   the terms of the GNU Lesser General Public License as published by the
8   Free Software Foundation; either version 2, or (at your option) any
9   later version.
10
11   OGo is distributed in the hope that it will be useful, but WITHOUT ANY
12   WARRANTY; without even the implied warranty of MERCHANTABILITY or
13   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
14   License for more details.
15
16   You should have received a copy of the GNU Lesser General Public
17   License along with OGo; see the file COPYING.  If not, write to the
18   Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
19   02111-1307, USA.
20 */
21 // $Id$
22
23 /*
24   A small demonstration program to show how to write a SAX handler
25   using SaxObjC. It goes over a RSS channel file and collects the
26   item information in a dictionary.
27   
28   This example is almost the same like rss2plist1.m, but uses the
29   SaxMethodCallHandler which calls a method for each tag, so you
30   don't need to do manual tagname checks.
31   Note that we only process known content, all other tags are ignored.
32   
33   As you will see it's quite a bit of work dealing with SAX ;-)
34 */
35
36 #import <Foundation/Foundation.h>
37 #include <SaxObjC/SaxObjC.h>
38 #include <SaxObjC/SaxMethodCallHandler.h>
39
40 /* ******************** the SAX handler ****************** */
41
42 @interface RSSSaxHandler : SaxMethodCallHandler
43 {
44   NSMutableArray      *entries;
45   NSMutableDictionary *entry;
46
47   /* parsing state */
48   NSString *value;   /* the (PCDATA) content of a tag */
49 }
50
51 - (NSArray *)rssEntries;
52
53 @end
54
55 @implementation RSSSaxHandler
56
57 - (id)init {
58   if ((self = [super init])) {
59     self->entries = [[NSMutableArray alloc] initWithCapacity:16];
60     self->entry   = [[NSMutableDictionary alloc] initWithCapacity:8];
61     
62     /* those are required for mapping the names */
63     [self registerNamespace:@"http://purl.org/rss/1.0/" withKey:@"rss"];
64     [self registerNamespace:@"http://www.w3.org/1999/02/22-rdf-syntax-ns#"
65           withKey:@"rdf"];
66     [self registerNamespace:@"http://purl.org/rss/1.0/modules/slash/"
67           withKey:@"slash"];
68     [self registerNamespace:@"http://purl.org/rss/1.0/modules/syndication/"
69           withKey:@"syn"];
70   }
71   return self;
72 }
73 - (void)dealloc {
74   [self->entry   release];
75   [self->entries release];
76   [super dealloc];
77 }
78
79 /* accessing results */
80
81 - (NSArray *)rssEntries {
82   return [[self->entries copy] autorelease];
83 }
84
85 /* setup/teardown */
86
87 - (void)startDocument {
88   /* ensure consistent state */
89   [self->entries removeAllObjects];
90 }
91
92 /* parsing */
93
94 - (void)start_rssitem:(id<SaxAttributes>)_attributes {
95   [self->entry removeAllObjects];
96 }
97 - (void)end_rssitem {
98   [self->entries addObject:[[self->entry copy] autorelease]];
99 }
100
101 /* the subtags of item ... */
102
103 - (void)start_rsstitle:(id<SaxAttributes>)_attributes {
104   [self->value release]; self->value = nil;
105 }
106 - (void)end_rsstitle {
107   if (self->value)
108     [self->entry setObject:self->value forKey:@"title"];
109 }
110
111 - (void)start_rsslink:(id<SaxAttributes>)_attributes {
112   [self->value release]; self->value = nil;
113 }
114 - (void)end_rsslink {
115   if (self->value)
116     [self->entry setObject:self->value forKey:@"link"];
117 }
118
119 - (void)start_rssdescription:(id<SaxAttributes>)_attributes {
120   [self->value release]; self->value = nil;
121 }
122 - (void)end_rssdescription {
123   if (self->value)
124     [self->entry setObject:self->value forKey:@"info"];
125 }
126
127 - (void)characters:(unichar *)_chars length:(int)_len {
128   NSString *s;
129   
130   /* 
131      Note: The characters callback is allowed to be called multiple times
132            by the parser (makes writing parsers easier, but complicates the
133            handler ...).
134   */
135   s = [[NSString alloc] initWithCharacters:_chars length:_len];
136   if (self->value) {
137     self->value = [[self->value stringByAppendingString:s] copy];
138     [s release];
139   }
140   else
141     self->value = s;
142 }
143
144 @end /* RSSSaxHandler */
145
146 /* ******************** C main section ******************** */
147
148 int main(int argc, char **argv, char **env) {
149   NSAutoreleasePool *pool;
150 #if LIB_FOUNDATION_LIBRARY
151   [NSProcessInfo initializeWithArguments:argv count:argc environment:env];
152 #endif
153   
154   pool = [[NSAutoreleasePool alloc] init];
155
156   if ([[[NSProcessInfo processInfo] arguments] count] < 2) {
157     fprintf(stderr, "usage: %s <rssfile>\n",
158             [[[[NSProcessInfo processInfo] arguments] lastObject] cString]);
159     return 1;
160   }
161   
162   /* the interesting section */
163   {
164     NSEnumerator     *args;
165     NSString         *arg;
166     id<SaxXMLReader> parser;
167     RSSSaxHandler    *sax;
168     
169     /* step a, get a parser for XML */
170     parser = [[SaxXMLReaderFactory standardXMLReaderFactory]
171                                  createXMLReaderForMimeType:@"text/xml"];
172     
173     /* step b, create a SAX handler and attach it to the parser */
174     sax = [[[RSSSaxHandler alloc] init] autorelease];
175     [parser setContentHandler:sax];
176     [parser setErrorHandler:sax];
177     
178     /* step c, parse :-) */
179     
180     args = [[[NSProcessInfo processInfo] arguments] objectEnumerator];
181     [args nextObject]; /* skip tool name */
182     
183     while ((arg = [args nextObject])) {
184       NSArray *entries;
185       
186       /* the parser takes URLs, NSData's, NSString's */
187       arg = [[[NSURL alloc] initFileURLWithPath:arg] autorelease];
188       
189       /* let the parser parse (it will report SAX events to the handler) */
190       [parser parseFromSource:arg];
191       
192       /* now query the handler for the result */
193       entries = [sax rssEntries];
194       
195       /* TODO: use NSPropertyListSerialization on OSX */
196       printf("%s\n", [[entries description] cString]);
197     }
198     
199     return 0;
200   }
201   [pool release];
202   return 0;
203 }