Using RDF iCalendar with RSS 1.0

Libby Miller, 2004-04-29

[@@Note: an experimental (and unfinished) writeup to suggest how we might approach the applications and demonstrations taskforce (ADTF) in the Semantic Web Best Practices working group.]

RDF iCalendar is ongoing work to convert the iCalendar RFC 2445 to RDF. An RDF/OWL schema is available. People often ask how to represent events in RSS 1.0. This document

Introduction

RSS 1.0 is a simple way of describing a list of links such as news stories. It can be extended using 'modules' - little extensions for specific purposes. Because it is written in RDF it can also be extended with any arbitrary RDF. One such candidate is the RDF iCalendar vocabulary, an RDF version of the main calendaring standard iCalendar, created using an informal community process. Many personal information managment tools use iCalendar, so using RDF iCalendar - which can be losslessly roundtripped to iCalendar - is a good basis for interoperablity with existing tools.

Combining RSS 1.0 and RDF iCalendar

Here's what an RSS 'item' (the most interesting fragment of an rss channel) might look like:

<item rdf:about="http://www2004.org/">
 <title>The Thirteenth International World Wide Web 
Conference</title>
 <description>The Thirteenth International World Wide Web 
Conference will be held May 17-22, New York Sheraton, New York, 
USA.</description>
 <link>http://www2004.org/</link>
</item>

and here's the same using RDF iCalendar to provide more structured information about the event:

<item rdf:about="http://www2004.org/">
 <title>The Thirteenth International World Wide Web 
Conference</title>
 <description>The Thirteenth International World Wide Web 
Conference will be held May 17-22, New York Sheraton, New York, 
USA.</description>
 <link>http://www2004.org/</link>

 <foaf:topic>
   <ical:Vevent>
    <ical:url rdf:resource="http://www2004.org/"/>
    <foaf:homepage rdf:resource="http://www2004.org/"/>
    <ical:dtstart rdf:parseType="Resource">
     <ical:date>2004-05-17</ical:date>
    </ical:dtstart>
    <ical:dtend rdf:parseType="Resource">
     <ical:date>2004-05-22</ical:date>
    </ical:dtend>
    <ical:description>The Thirteenth International World Wide Web 
Conference</ical:description>
    <ical:location>New York, USA</ical:location>
    <ical:organizer rdf:parseType="Resource">
     <ical:calAddress rdf:resource="mailto:info@www2004.org"/>
    </ical:organizer>
  </ical:Vevent>
 </foaf:topic>
</item>

The key thing to note is the indirection between the item's url (http://www2004.org) and the event itself. The event is not the same thing as the page describing it, and so we use foaf:topic to indicate that the page given by the url is a page about the event.

Another thing to notice is the use of foaf:homepage to identify the event. foaf:homepage is an owl:inverseFunctionalProperty, which means that the homepage serves as a key to identify the subject - the event. This means that it should be used with care: for example, if foaf:homepage is used to identify a specific presentation within the conference as well as the conference itself, then the two events will be merged together incorrectly by owl-conforming tools. foaf:homepage has different semantics to ical:url, which refers to a page which may have a more recent version of the calendar on it.

@@Example with times, timezones.

Pseudo-code examples

Get me all events starting in May 2004

String query="select ?start, ?end, ?description, ?homepage "+
 where 
 (foaf:homepage ?event ?homepage) 
 (ical:dtstart ?event ?d1) 
 (ical:date ?d1 ?start)
 (ical:dtend ?event ?d2) 
 (ical:date ?d2 ?end)
 (ical:description ?event ?desc) 
 and ?start ~ '2004-05' 
using foaf for http://xmlns.com/foaf/0.1/
and ical for http://www.w3.org/2002/12/cal/ical#

RDFGraph g =
RDFGraph.load("http://www.w3.org/2000/06/webdata/xslt?xslfile=http://www.w3.org/2001/sw/Europe/200211/swconferences/home2rssical.xsl&xmlfile=http://www.w3.org/2001/sw/Europe/200211/swconferences/events1.html");

Resultset r = g.askRDFQuery(query);

	while(r.next){
	print(r.get("desc")+" "+r.get("start")+" "+r.get("end")+" "+r.get("homepage"));
	}


Get me all the attendees of the conference with homepage http://www2004.org

String query="select ?mbox "+
 where 
 (foaf:homepage ?event http://www2004.org) 
 (rdf:type ?event http://www.w3.org/2002/12/cal/ical#Vevent)
 (ical:attendee ?event ?caluser)
 (ical:caladdress ?caluser ?mbox) 
using foaf for http://xmlns.com/foaf/0.1/
ical for http://www.w3.org/2002/12/cal/ical#
rdf for http://www.w3.org/1999/02/22-rdf-syntax-ns#

RDFGraph g =
RDFGraph.load("http://www.w3.org/2000/06/webdata/xslt?xslfile=http://www.w3.org/2001/sw/Europe/200211/swconferences/home2rssical.xsl&xmlfile=http://www.w3.org/2001/sw/Europe/200211/swconferences/events1.html");
g.load("http://www.w3.org/2001/sw/Europe/200211/swconferences/www2004.rdf");//attendee information

Resultset r = g.askRDFQuery(query);

	while(r.next){
	print(r.get("mbox"));
	}


Display all the events in May 2004 in a user-friendly table

..

Convert this RSS+ RDF iCalendar to iCalendar for download

String query="select ?event "+
 where 
 (rdf:type ?event http://www.w3.org/2002/12/cal/ical#Vevent)
using rdf for http://www.w3.org/1999/02/22-rdf-syntax-ns#

RDFGraph g =
RDFGraph.load("http://www.w3.org/2000/06/webdata/xslt?xslfile=http://www.w3.org/2001/sw/Europe/200211/swconferences/home2rssical.xsl&xmlfile=http://www.w3.org/2001/sw/Europe/200211/swconferences/events1.html");

Resultset r = g.askRDFQuery(query);

print 
"BEGIN:VCALENDAR
CALSCALE:GREGORIAN
METHOD:PUBLISH
PRODID:-//example to iCalendar//EN
VERSION:2.0";


	while(r.next){
	print("BEGIN:VEVENT");
	Node e = r.get("event");

	String q1="select ?summary  where 
	 (ical:summary "+e+" ?summary)
	using ical for http://www.w3.org/2002/12/cal/ical#";

	   Resultset r1 = g.askRDFQuery(q1);
		if(r1.next()){
		print("SUMMARY:"+r1.get("summary")+"\n");
		//note - limited number of characters per line
		}

	String q2="select ?start  where 
	 (ical:dtstart "+e+" ?date)
	 (ical:date ?date ?start) 
	using ical for http://www.w3.org/2002/12/cal/ical#";

	   Resultset r2 = g.askRDFQuery(q2);
		if(r2.next()){
		print("DTSTART:"+r2.get("start")+"\n");
		}

	String q3="select ?end  where 
	 (ical:dtend "+e+" ?date)
	 (ical:date ?date ?end) 
	using ical for http://www.w3.org/2002/12/cal/ical#";

	   Resultset r3 = g.askRDFQuery(q3);
		if(r3.next()){
		print("DTEND:"+r3.get("end")+"\n");
		}

	}

print "END:VCALENDAR\n";

Pitfalls

representing timezones
accidentally merging events
being clear about start and end for dates without times (icalendar)
line lengths (icalendar)
converting repeating events
implementation-specific icalendar issues

Other approaches/further reading

RSS + events module

RSS variants

RDF icalendar work links

foaf spec

RDF, Owl specs