iCalendar/vCalendar parsing routine

Bastiaan Olij bastiaan at basenlily.me
Fri Mar 8 00:52:18 EST 2013


Hey Gary,

Currently I only create them out of Omnis, I'm working on parsing them
but we're parsing them server side and thus not in Omnis.

The structure however is really simple. Recurring events are a pain but
normal invites are pretty easy to parse and get the relevant information
from.
The basic structure revolves around blocks that are heirachical. Each
block starts with BEGIN:<type> and ends with END:<type>

The main block is always:
BEGIN:VCALENDAR
...
END:VCALENDAR

The blocks you will find within are:
VEVENT, holding the event information itself
VALARM, holding information about when someone should be alerted of the
event

There are other blocks but these I work with most.
A VEVENT is contained within a VCALENDAR but this heirarchy is fixed so
you won't find a VEVENT inside of a VEVENT.

Other then that the data holds values in the form:
<name>:<value>

So a really simple event would look like:
BEGIN:VCALENDAR
VERSION:2.0
BEGIN:VEVENT
DTSTART:20130202T101000Z
DTEND:20130202T102000Z
END:EVENT
END:VCALENDAR

This would be an event scheduled at 10:10am on the 2nd of February 2013
(The Z means its GMT) and nobody is invited.
Both the name and the value can have additional properties that are
delimited with a ; so:
DTSTART;VALUE=DATE:20130202
Denotes that the start date doesn't have a time.
Similarly if a time zone is involved it will be included similarly as well.

Important name/value pairs for VEVENT are:
UID, a unique ID for this event
DTSTART, start of the event
DTEND, end of the event
SUMMERY, title of the event
DESCRIPTION, description of the event
ORGANISER, the person who organised the event (value is usually the
email address)
ATTENDEE, the person(s) invited (value is usually the email address), if
multiple people are invited multiple of these records exist

Important name/value pars for VALARM are:
ACTION, what to do with the alarm, display, sound, etc?
DESCRIPTION, description of the alarm
ATTENDEE, the person the alarm is for (if multiple people there will be
multiple VALARM blocks, one per person)
TRIGGER, when should the alarm go off (can be relative)

Lines are CR LF delimited, if the value has newlines the LF is escaped
(\n) leaving only CRs. "Some" calendar clients also escape the CRs.

Just working from memory here but I would start with the code below:
----
oICS.$construct
--
;; Define my list
Do ivList.$cols.$add('Name',kCharacter,kSimpleChar,1000000)
Do ivList.$cols.$add('Value',kCharacter,kSimpleChar,1000000)
Do ivList.$cols.$add('Details',kList)

oICS.parseBlocks(pvList fieldref)
--
;; create a list for our details
lvList.$copylistdefinition(ivList)

;; while there are blocks in our list...
While pvList.$search($ref.Name='BEGIN',ktrue,kfalse,kfalse,kfalse)>0
  Calculate lvBlock as pvList.Value
  Calculate lvStart as pvList.$line
  if
pvList.$search($ref.Name='END'&$ref.Value=lvBlock,ktrue,kfalse,kfalse,kfalse)>0
    Calculate lvEnd as pvList.$line

    ;; select related lines and move them into our details list
    Do pvList.$search(pvList.$line>=lvStart&pvList.$line<=lvEnd,kTrue,
kFalse, kTrue, kTrue)
    Do lvList.$merge(pvList,kTrue,kTrue,kTrue)
    Do pvList.$remove(kListDeleteSelected)

    ;; remove our begin and end line
    Do pvList.$remove(lvEnd)
    Do pvList.$remove(pvStart)

    ;; And call recursively
    Do method parseBlocks (lvList)
   
    ;; And add the result back into our main list
    Do pvList.$addbefore(lvStart, lvBlock, '', lvList)
  else
    ;; badly formed iCal data!
    calculate pvList.Name as pvList.Value
    calculate pvList.Value as ''
  end if
End while

oICS.$parseICS(pvICS)
--
Do ivList.$clear()

While len(pvICS)>0
  ;; get the next line
  Calculate lvPos as pos(con(kCR,kLF), con(pvICS, kCR, kLF))
  Calculate lvLine as mid(pvICS,1,lvPos-1)
  Calculate lvICS as mid(pvICS,lvPos+1,len(pvICS))

  ;; we ignore empty lines, there shouldn't be any
  If len(lvLine)>0
    Calculate lvPos as pos(':', con(pvLine,':'))
    Do lvList.$add(mid(pvLine,1,lvPos-1), mid(pvLine,lvPos+1,len(pvLine))
  End if
End while

Do method parseBlocks (ivList)
----

If I didn't make any typo's calling $parseICS with the contents of your
.ics file should result in all your blocks being loaded into the detail
lists and all your name/value pairs should be split out nicely and its a
matter of looping through the lists to extract the data you need.

Heck you can probably get away by not calling parseBlocks but just
looping through the name/value pairs extracting what you need.

Cheers,

Bas

On 8/03/13 10:30 AM, Gary Connor wrote:
> Has anyone built a routine for parsing Microsoft vcalendar or more standard .ics and .vcf files?  We routinely get these in or attached to emails from clients, and would like to parse them into our own Studio apps.  Hoping to avoid re-inventing the wheel.
> ________________________________
> Dr. Gary Connor, PhD, CIO
> DirectLine Technologies, Inc.
> 1600 N. Carpenter Road
> Building D
> Modesto, CA 95351
> (209) 491-2020
>
>
> ----------------------------------------------------------------------------------------
> The information contained in this email and any attachments is confidential
> and may be subject to copyright or other intellectual property protection.
> If you are not the intended recipient, you are not authorized to use or disclose
> this information, and we request that you delete the original message from
> your mail system.
> _____________________________________________________________
> Manage your list subscriptions at http://lists.omnis-dev.com
>
>





More information about the omnisdev-en mailing list