Question

I'm looking for an easy way to parse VCALENDAR data with objective-c. Specifically all I am concerned with is the FREEBUSY data (See below):

BEGIN:VCALENDAR
VERSION:2.0
METHOD:REPLY
PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
BEGIN:VFREEBUSY
UID:XYZ-DONT-CARE
DTSTART:20090605T070000Z
DTEND:20090606T070000Z
ATTENDEE:/principals/__uids__/ABC1234-53D8-4079-8392-01274F97F5E1/
DTSTAMP:20090605T075430Z
FREEBUSY;FBTYPE=BUSY:20090605T170000Z/20090605T200000Z,20090605T223000Z/20
 090606T003000Z
FREEBUSY;FBTYPE=BUSY-UNAVAILABLE:20090605T070000Z/20090605T150000Z,2009060
 6T010000Z/20090606T070000Z
ORGANIZER:/principals/__uids__/ABC1234-53D8-4079-8392-01274F97F5E1/
END:VFREEBUSY
END:VCALENDAR

I've tried parsing it by using componentsSeparatedByString:@"\n", but there is a \n in part of the FREEBUSY data, causing it to not parse correctly.

Is there something easy that I'm missing?

Was it helpful?

Solution

The \n in the middle of FREEBUSY data is a part of the iCalendar spec; according to RFC 2445, the newline followed by a space is the correct way to split long lines, so you'll probably see a lot of this in scanning FREEBUSY data.

As Nathan suggests, an NSScanner may be all you need if the data you're expecting will be reasonably consistent. There are a number of vagaries in iCalendar, though, so I often find myself using libical to parse ics info. An quick-and-dirty example of parsing this data using libical:

NSString *caldata = @"BEGIN:VCALENDAR\nVERS....etc";

icalcomponent *root = icalparser_parse_string([caldata cStringUsingEncoding:NSUTF8StringEncoding]);

if (root) {

    icalcomponent *c = icalcomponent_get_first_component(root, ICAL_VFREEBUSY_COMPONENT);

    while (c) {
        icalproperty *p = icalcomponent_get_first_property(c, ICAL_FREEBUSY_PROPERTY);

        while (p) {
            icalvalue *v = icalproperty_get_value(p);
            // This gives: 20090605T170000Z/20090605T200000Z
            // (note that stringWithCString is deprecated)
            NSLog(@"FREEBUSY Value: %@", [NSString stringWithCString:icalvalue_as_ical_string(v)]);
            icalparameter *m = icalproperty_get_first_parameter(p, ICAL_FBTYPE_PARAMETER);

            while (m) {
                // This gives: FBTYPE=BUSY
                NSLog(@"Parameter: %@", [NSString stringWithCString:icalparameter_as_ical_string(m)]);
                m = icalproperty_get_next_parameter(p, ICAL_FBTYPE_PARAMETER);
            }

            p = icalcomponent_get_next_property(c, ICAL_FREEBUSY_PROPERTY);
        }

        c = icalcomponent_get_next_component(root, ICAL_VFREEBUSY_COMPONENT);
    }

    icalcomponent_free(root);
}

Documentation for libical is in the project download itself (see UsingLibical.txt). There's also this lovely tutorial on shipping libical in your application bundle.

OTHER TIPS

Take a look at NSScanner.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top