You are on page 1of 13

Toolkit to assist organisations in implementing online

iCAL format data feeds to support the sharing of


events information with individuals and other
organisations.
Commissioned by the Higher Education Academy/JISC collaboration project
in support of the Unified Events Calendar project.

Compiled by Mr Rob Pearce, The Higher Education Academy Engineering


Subject Centre, Loughborough University.

Page 1 of 13
Index:

........................................................................................................................1
........................................................................................................................1
........................................................................................................................1
Index:..............................................................................................................2
Background....................................................................................................2
Academy/JISC collaboration Unified Events Calendar project rationale.. .2
Why the iCAL format and not RSS?...........................................................3
Solutions Scenarios........................................................................................3
Other useful resources:..................................................................................5
Appendix A: PHP code Solution for producing iCAL from a database..........7
Appendix B: ASP code solution for producing iCAL from a database...........8

Background

Academy/JISC collaboration Unified Events Calendar project


rationale.

The primary intention of the project is to help enable the Collaboration


Network (All the organisations which are part of the Higher Education
Academy and JISC and its related projects and supported organisations) to
share information about events.

o By providing your events information in iCAL format you will enable the
growing number of individuals in your community with personal
calendars to add details of your events quickly and error-free by
integrating a 1-click process straight into their normal workflow.

o If you work for a subject centre or JISC organisation you can also be
actively involved in the shared calendar initiative which allows a unified
view of all events happening within our community – useful for both the
community, 3rd party event aggregation and events planners within our
own organisations.

o Once you have implemented iCAL there are potentially many new
approaches, collaboration and syndication opportunities you might be
well positioned to initiate or respond to in the future.

Page 2 of 13
Why the iCAL format and not RSS?
RSS is an excellent way to share events information between humans via
computers, but machines struggle to turn RSS’s simple textual statements,
meant ultimately for humans to read, into consistent formatted calendar
“events”.
iCAL was designed specifically to transmit event information from machine to
machine and has become a widely adopted standard.
RSS could still be used; if the event date information was presented in a
consistent and distinctive way in the title of each RSS entry, free services like
Yahoo Pipes could be used to convert this to create a simple iCAL feed.

Solutions Scenarios
NB: These are just some of the ways you can approach this task.

Scenario: I’ve got a hand-typed events webpage, no databases and no


internal calendar system.
Solution: Use a free online calendar service, for instance, Google Calendar.
Level: Easy
Time: 0.5 day

Instructions: Create a free Google account (this has many other advantages
beyond calendaring and is recommended). Add your events via the easy-to-
use interface then just cut and paste the linking code created to reproduce an
interactive calendar easily on your website.

Benefits: you can also add other events details from centres or other
organisations to your own calendar. Your event details can also appear in
Google Web Search or Google Calendar search results if you choose. Also
generates an iCAL feed automatically for you.

Issues: The service is currently “beta” (not completely finished) but does seem
to be working at present. Each event has a link on it for more details but this
link takes the user to Google Maps – not necessarily the preferred option.

Scenario: I’ve got all our public events details stored in Outlook.
Solution: Convert the data into iCAL format on your PC or Mac.
Level: Easy
Time: Quick!

Instructions: You need to add a free macro (Outlook to iCal Export Utility for
Windows) to your copy of Outlook. Details and download here:
http://outlook2ical.sourceforge.net/
Follow the comprehensive instructions then take the resulting .ics file (e.g;all-
our-events.ics) and put it anywhere on your website. Provide a link to the file
on your website.

Page 3 of 13
Benefits: Simple and free requiring little change to working patterns

Issues: You’ll need to repeat this process as you add new events. As long as
you use the same filename for the .ics file and replace old with new then all
your links and any websites displaying your information will stay the same.

Scenario: I’ve got a publicly available events webpage we either hand-edit or


use a database to list events information on and we don’t want to get more
technical than that.

Solution: Use Dapper ( http://www.dapper.net/ ) to generate an iCAL feed.


Level: Easy
Time: 0.5 day

Instructions: Dapper is a free, web-based service that allows you to extract


and use information from any publically available webpage. It allows you to
create a "feed" for any site without programming. You can then use these
feeds in a variety of ways: as an RSS feed, an iCAL feed etc. Follow the link
above and create an account. The 4-step “wizard” type process to create a
feed is well documented. It may take several attempts to get the right result.
The “Select Inside” function is particularly useful; if for instance the start and
finish dates for an event are placed together with a separating character such
as dash you can tell Dapper to split the dates and they can then be
communicated via iCAL properly as separate items of information.

Benefits: The free service does the work of converting your information into
the right format. You may have to be prepared to make a few small
adjustments to your events information layout on your website.

Issues: The service does a fairly intelligent job, but isn’t always able to create
feeds in all cases, the level of success depends on the quality and
consistency of the page construction and consistent formatting of the
information presented there. Dapper will not include entries into the feed it
cannot fully understand. A test on an events page listing 25 events produced
an accurate iCAL feed of 12 events. (The drop-outs were due to ambiguous
event date descriptions that could be relatively easily corrected).

Scenario: Our website is powered by a content management system X.


Solution: Add an existing calendar module/plugin to your setup.
Level: Variable
Time: Variable

Instructions: Most CMS systems have modules that can easily be added to
provide calendar functionality, e.g Drupal: http://drupal.org/project/webcal both
for the display and generation of iCAL feeds. Comprehensive details are

Page 4 of 13
beyond the scope of this document but vendor or user community should be
able to help.

Scenario: I’ve got some scripting (programming) experience, a database with


my events in and I run PHP/ASP/.NET on my server.
Solution: Coding a solution is no more difficult than pulling textual information
from a store, applying simple formatting and putting the resulting text file live
on a web server.
Level: technical
Time: 1-2 days

Instructions: See appendices A, B, and C for PHP, ASP and .NET example
solutions already in use. These examples have been written for specific
configurations of servers and databases and will require some customisation
in order to function with other configurations.

Benefits: Full control over creating an automatically updated feed and the
possibility of producing custom feeds in the future. The ASP code in appendix
B. also creates an individual iCAL file for each event which can be exposed
on the events page of a website allowing those with iCAL ready software like
Microsoft Outlook to import details straight into their calendars.

Issues: none

Scenario: I’ve heard a lot about the free Mozilla Sunbird software package
both to produce iCAL feeds, manage an event calendar and to draw on
external iCAL feeds from other sources on my server.
Solution: Download the software from here:
http://www.mozilla.org/projects/calendar/sunbird/
Level: non-technical
Time: 1 day

Instructions: See comprehensive instructions on the web.

Benefits: One-stop-shop

Issues: none

Other useful resources:

iCAL RFC (original iCAL feed specification): http://www.ietf.org/rfc/rfc2445.txt

Page 5 of 13
An iCAL feed Validator for testing new feeds:
http://severinghaus.org/projects/icv/

A copy of the defacto-standard iCAL logo here:


http://www.engsc.ac.uk/nef/nefimages/ical.gif
Right click and “Save as..” or similar depending on your browser type.

Demo of all the Higher Education Academy/JISC Unified calendar Project and
Academy iCAL feeds already available:
http://www.engsc.ac.uk/rssfeeds/caldemo.htm

Academy Gateway project Wiki, maintained by Terry McAndrew, contains


information about the Gateway initiative including the shared calendar project:
http://heabiowiki.leeds.ac.uk/gateway/index.php/Main_Page

If you have problems with your iCAL feed contact rob Pearce on
rob@engsc.ac.uk

Page 6 of 13
Appendix A: PHP code Solution for producing iCAL from a
database

The PHP solution requires a free library which can be downloaded from
http://www.phpclasses.org/browse/package/3478.html which includes code
examples. (Registration for the library is free)

Code: (This code was developed and kindly shared by the Information and
Computer Sciences Subject Centre so some textual content, specific SQL
statements and references to database fields etc. will need to be modified.)
<?php require_once('../Connections/ltsncon.php'); // This is just the file with the information to connect to the
database?>
<?php require_once('iCalcreator.class.php'); // The php Library to create iCal files ?>
<?php
$datetoday = date("Y-m-d");
mysql_select_db($database_ltsncon, $ltsncon);
$query_events = "SELECT * FROM event_ics WHERE display='Y' AND start_date>='$datetoday' ORDER BY
start_date ASC"; // Get all events visible on website that have a date in the future in order
$events = mysql_query($query_events, $ltsncon) or die(mysql_error());
$row_events = mysql_fetch_assoc($events);
$totalRows_events = mysql_num_rows($events);
?>
<?php $v=new vcalendar(); // create a new vcalendar instance
$v->setConfig( "format", "ical" ); // set format to iCal
$v->setConfig( "allowEmpty", TRUE ); //Allows some setting to be empty
$v->setConfig('unique_id', 'www.ics.heacademy.ac.uk'); // A unique id used to tag events in the calendar
$v->setConfig( "filename", "ics_events.ics" ); // the name of the ics file to output.
$v->setProperty( "X-WR-CALNAME", "Information and Computer Sciences Subject Centre Calendar" ); // see
documentation on the iCal library for more in depth info
$v->setProperty( "X-WR-CALDESC", "Events Promoted by the ICS Subject Centre" );
$v->setProperty( "X-WR-TIMEZONE", "Europe/London" );
$v->setProperty('method', 'PUBLISH'); // this is required by some calendars such as Outlook 2003?>
<?php do {
$vevent = new vevent(); // create new event instance
list($yr,$mon,$day) = split('[- ]',$row_events['start_date']); // extract date data from the table in year, month
and day
$dateevent="".$yr.$mon.$day.""; // reformat date in iCal format
$vevent->setProperty('dtstart',array('year'=>$yr,'month'=>$mon,'day'=>$day)); //sets date start property on
event
if ($row_events['end_date']!=$row_events['start_date']){ // if the event last longer than a day
list($end_yr,$end_mon,$end_day) = split('[- ]',$row_events['end_date']);
$vevent->setProperty( 'dtend', array( 'year'=>$end_yr, 'month'=>$end_mon,
'day'=>$end_day+1)); // set end date for the event
}else{
$vevent->setProperty( 'dtend', array( 'year'=>$yr, 'month'=>$mon, 'day'=>$day+1)); // else, give
the end date as day+1. See documentation for explanation on why +1
}
if ($row_events['location']==NULL) {
$vevent->setProperty( 'LOCATION', $row_events['venue']); // In some of our events "location" is
empty and we use the value "venue" instead
}else{
$vevent->setProperty( 'LOCATION', $row_events['location']); // this block sets the correct
location in those cases.
}
$vevent->setProperty( 'summary', $row_events['title']); // I decided to use the title of the event as the
summary, since we don't have a summary for the event. I think this is what most others are also doing
if ($row_events['external']=='Y') {
$vevent->setProperty( "url", $row_events['ext_url']);
}else {
$vevent->setProperty( "url", "http://www.ics.heacademy.ac.uk/events/displayevent.php?id=".
$row_events['event_id']);
}// this sets the right URL for the event
$v->setComponent ( $vevent ); // add event to calendar
} while ($row_events = mysql_fetch_assoc($events)); // rinse and repeat for all events
$v->returnCalendar(); //write calendar to output file ?>

Page 7 of 13
Appendix B: ASP code solution for producing iCAL from a
database

Code: (This code was developed and kindly shared by the Engineering
Subject Centre so some textual content, specific SQL statements and
references to database fields etc. will need to be modified.)
Note this code produces several text files containing bits of iCAL output.
Inorder for the code to work it must have permission to create and delete text
files somewhere, that is whoever triggers the code must be a user with this
level of permissions. This is all easily possible but how this is approached and
the risks etc. of doing this is outside the scope of this document.
<%
'*** a lump of code that pulls details of all hi-lighted upcoming events from the database
'*** and wraps each of them in the correct iCAL format then writes out a complete list
'***of events into one file and one small iCAL file for each individual event
'*** names of those files are given below
'*** referring to RFC 2445

Set eventlist = Server.CreateObject("ADODB.Connection")


eventlist.open "driver=MySQL ODBC 3.51 Driver;server=localhost;database=events;uid=xxx;pwd=xxxxxxxx"

Dim sIcalfilelocation, sWritableVirDirLocation, sIndividualEventIcalFilename


Dim sIcalHeaderInfo, sIndividualIcalData, sAllEventIcalData, sIcalFooterInfo

'name of the ical file generated


'created in the virtual directory normally defined below at same level as web root
'so outside web dirs but then linked in virtually to engsc.ac.uk/information

sWritableVirDirLocation="F:\Web\information\engsc\"
sIcalfilelocation="allengscevents.ics"

'*** basic header data for iCAL format no colons or semi-colons


sIcalHeaderInfo="BEGIN:VCALENDAR" & vbCrLF
sIcalHeaderInfo=sIcalHeaderInfo & "PRODID:-//www.engsc.ac.uk//NONSGML Full Events Diary v1.0//EN" & vbCrLF
sIcalHeaderInfo=sIcalHeaderInfo & "X-WR-CALNAME:Engineering Subject Centre Highlighted Events Diary" &
vbCrLF
sIcalHeaderInfo=sIcalHeaderInfo & "X-WR-TIMEZONE:Europe/London" & vbCrLF
sIcalHeaderInfo=sIcalHeaderInfo & "X-WR-CALDESC:Events related to teaching and learning in Higher Education
Engineering." & vbCrLF

'*** basic footer data for iCAL format


sIcalFooterInfo="END:VCALENDAR"

'***make and execute SQL query to get all the relevent data
'***in this case the eng database has date and sometimes time infor as well as the usual
'***title, description etc.
'*** one special trick is to use the MySQL database to calculate a new date, startdate+1 day using a function
'***that takes a date and adds one to it. : DATE_FORMAT(DATE_ADD(datefrom, INTERVAL 1 DAY), '%Y%m%d') as
defaultenddate
'***This could be done directly using ASP if the
'***database in use cant do this
Set rsLTSNEvents = Server.CreateObject("ADODB.Recordset")
rsLTSNEvents.CursorLocation=3
rsLTSNEvents.Open "SELECT eventid, itimefrom, itimeto, event_name, ev_name_subtitle, dateto,
DATE_FORMAT(datefrom, '%Y%m%d') as shortdate, DATE_FORMAT(DATE_ADD(dateto, INTERVAL 1 DAY), '%Y
%m%d') as shortenddateplus1day, DATE_FORMAT(DATE_ADD(datefrom, INTERVAL 1 DAY), '%Y%m%d') as
defaultenddate, highlight, location, weblink, description FROM events WHERE datefrom>Now() AND highlight='Y'
ORDER BY datefrom", eventlist, 3, 3
'*** if it worked lets go and create a VEVENT entry for each event
if rsLTSNEvents.recordcount > 0 then

rsLTSNEvents.MoveFirst
do while Not rsLTSNEvents.eof
sIndividualIcalData="BEGIN:VEVENT" & vbCrLF

Page 8 of 13
if rsLTSNEvents("itimefrom")<>"" then
sIndividualIcalData=sIndividualIcalData & "DTSTART:"& rsLTSNEvents("shortdate") & "T"&
rsLTSNEvents("itimefrom") & "00Z"
else
sIndividualIcalData=sIndividualIcalData & "DTSTART;VALUE=DATE:"&
rsLTSNEvents("shortdate")
End if
sIndividualIcalData=sIndividualIcalData & vbCrLF
'***if there is an end date provided write it in otherwise put in default start date plus 1
if IsDate(rsLTSNEvents("dateto")) then
sTempDateInfo=rsLTSNEvents("shortenddateplus1day")
else
' if no end date provided but an end time is then make end date same as start date
' if no end time and no date provided then set to 1 day after the start date
if rsLTSNEvents("itimeto")<>"" then
sTempDateInfo=rsLTSNEvents("shortdate")
else
sTempDateInfo=rsLTSNEvents("defaultenddate")
End if
end if
if rsLTSNEvents("itimeto")<>"" then
sIndividualIcalData=sIndividualIcalData & "DTEND:"& sTempDateInfo
sIndividualIcalData=sIndividualIcalData & "T"& rsLTSNEvents("itimeto") & "00Z"
else
sIndividualIcalData=sIndividualIcalData & "DTEND;VALUE=DATE:"& sTempDateInfo
End if
sIndividualIcalData=sIndividualIcalData & vbCrLF

sIndividualIcalData=sIndividualIcalData & "SUMMARY:" & cleantxt(rsLTSNEvents("event_name"))


sIndividualIcalData=sIndividualIcalData & vbCrLF & "DESCRIPTION:" & cleantxt( rsLTSNEvents("description"))
& vbCrLF
sIndividualIcalData=sIndividualIcalData & "LOCATION:" & cleantxt(rsLTSNEvents("location")) & vbCrLF
sIndividualIcalData=sIndividualIcalData & "URL:" & cleantxt(rsLTSNEvents("weblink")) & vbCrLF
sIndividualIcalData=sIndividualIcalData & "END:VEVENT" & vbCrLF

' this bit of code writes an individual ical file for each specific event
' ***create and Write ical file
'***if you dont want these just comment out or delete the next 6 lines of code
sIndividualEventIcalFilename= rsLTSNEvents("eventid") & ".ics"
Set filesys2 = CreateObject("Scripting.FileSystemObject")
Set indivIcalFile = filesys2.CreateTextFile(sWritableVirDirLocation & sIndividualEventIcalFilename, True)
indivIcalFile.WriteLine sIcalHeaderInfo & sIndividualIcalData & sIcalFooterInfo
indivIcalFile.Close
set filesys2=nothing

' keep acumulating each indiv ical data for the whole list file
sAllEventIcalData=sAllEventIcalData & sIndividualIcalData

rsLTSNEvents.MoveNext
loop

' ***create and Write ical file containing all event details

Set filesys = CreateObject("Scripting.FileSystemObject")


Set filetoholdIcal = filesys.CreateTextFile(sWritableVirDirLocation & sIcalfilelocation, True)
filetoholdIcal.WriteLine sIcalHeaderInfo & sAllEventIcalData & sIcalFooterInfo
filetoholdIcal.Close
set filesys=nothing

End if
rsLTSNEvents.close
set rsLTSNEvents=nothing

' Common Functions


'*** this function adds all the necessary formating bits and bobs
'*** to any text going out so it complys with the standard

Function cleantxt(content)
Dim tmpchar, tmpstring

' check each char in string for certain special chars


' and remove(CR, ASCII code 13) and Line Feed
tmpstring =""
for cc = 1 to len(content)

Page 9 of 13
tmpchar=Mid(content, cc , 1)
aval=Asc(tmpchar)
' special case to replace hi ASCII code for a long hyphen (-) with a normal hyphen (Can trip some parsers up)
if (tmpchar = "-") then tmpstring = tmpstring & "-"

if (aval = 146 or aval=145) then ' special case to replace ASCII code 146 (single speech marks) with apostrophe
tmpstring = tmpstring & "'"
' then check for all other special or reserved chars
' remove Line Feed (LF, ASCII code 10)
elseif aval = 10 then
tmpstring = tmpstring & ""
' replace(CR, ASCII code 13) and replace with the accepted standard "\n"
elseif aval = 13 then
tmpstring = tmpstring & "\n"
' add a backslash before any commas, semicolons or existing backslashs(92)
elseif tmpchar = "," OR tmpchar = ";" OR tmpchar="\" then ' check for all other special chars
tmpstring = tmpstring & "\" & tmpchar

else
tmpstring = tmpstring & tmpchar
End if
Next
cleantxt=tmpstring
End Function
%>

Page 10 of 13
Appendix C: .NET code solution for producing iCAL from a
database

Code: (This code was developed and kindly shared by the Subject Centre for
Languages, Linguistics and Area Studies so some textual content, specific
SQL statements and references to database fields etc. will need to be
modified.)
‘gets a list of fields from a DB, makes them into a .NET memory table and writes them out to the end-user. It's
‘The strip_html() function is there to remove html from the description field
‘The get_db_conn() function just gets a DB connection object.

<%@ Page Language="VB" ContentType="text/html" ResponseEncoding="utf-8" smartNavigation="True" %>


<%@ Import Namespace="System.Data" %>
<%@ Import Namespace="System.Data.SqlClient" %>
<%@ Import Namespace="System.IO" %>
<%@ Import Namespace="System.Text.RegularExpressions" %>

<script runat="server">

Private Sub Page_Load()


Dim LanguagesConnection
Dim DownloadCmd
Dim SqlString

If Not IsPostBack Then


'Connect to Db and do SQl query to get all forthcoming events from resource table
LanguagesConnection = get_llas_db_conn()
LanguagesConnection.Open
SqlString = "SELECT resourceid, Title, Description, EventStart, EventEnd FROM Resources1 WHERE
LLASTypeID = 10 AND ( EventStart > GETDATE() ) ORDER BY cast(EventSort as datetime) ASC"
'Fill data table variable with SQL query results
Dim adapter as New SqlDataAdapter()
Adapter.SelectCommand = New SqlCommand(SqlString, LanguagesConnection)
Dim ev As new datatable
Adapter.Fill(ev)
LanguagesConnection.Close()

'set up http headers


Response.ContentType="text/calendar"
Response.CharSet = "utf-8"
'start file output
Response.write("BEGIN:VCALENDAR" & vbcrlf)
Response.write("VERSION:2.0" & vbcrlf)
Response.write("PRODID:-//www.llas.ac.uk//All forthcoming events//EN" & vbcrlf)
Response.write("X-WR-CALNAME:LLAS Subject Centre Forthcoming Events" & vbcrlf)
Response.write("X-WR-TIMEZONE:Europe/London" & vbcrlf)
Response.write("X-WR-CALDESC:Events related to teaching and learning in Higher Education
Langauges, Linguistics and Area Studies subjects." & vbcrlf)

'loop through each event item and write it out


Dim i
For i = 0 to (ev.rows.count-1)
Dim DTstart_date as datetime = ev.rows(i)("EventStart")
Dim DTend_date as datetime = ev.rows(i)("EventEnd")
Dim HTMLdescription = ev.rows(i)("Description")
Dim stringlines() as string = HTMLdescription.split(chr(13))
Dim this_url = "http://www.llas.ac.uk/events/" & ev.rows(i)("ResourceID")
Dim line
Dim location
For Each line in stringlines
If line.IndexOf("Location:") <> -1 then
'remove leading carriage return
location = line.substring(1)
location = StripHTML(location)
location = location.substring(location.IndexOf("Location:")+10)
End If
Next
Response.write("BEGIN:VEVENT" & vbcrlf)
' Response.write("UID:LLAS" & dr.item("resourceid") & vbcrlf)
Response.write("DTSTART:" & DTstart_date.ToString("yyyyMMdd\T09mmss\Z") & vbcrlf)

Page 11 of 13
Response.write("DTEND:" & DTEnd_date.ToString("yyyyMMdd\T09mmss\Z") & vbcrlf)
Response.write("SUMMARY:" & ev.rows(i)("Title") & vbcrlf)
Response.write("LOCATION:" & location & vbcrlf)
Response.write("URL:" & this_url & vbcrlf)
Response.write("END:VEVENT" & vbcrlf & vbcrlf)
Next
Response.write("END:VCALENDAR")
Response.End()
End If
End Sub

Public Function StripHTML(ByVal Source As String) As String


Dim result As String

' Remove HTML Development formatting


result = Source.Replace("\r", " ") ' Replace line breaks with space because browsers inserts
space
result = result.Replace("\n", " ") ' Replace line breaks with space because browsers inserts
space
result = result.Replace("\t", String.Empty) ' Remove step-formatting

' Remove remaining tags like <a>, links, images, comments etc - anything thats enclosed inside < >
result = System.Text.RegularExpressions.Regex.Replace(result, "<[^>]*>", String.Empty,
System.Text.RegularExpressions.RegexOptions.IgnoreCase)

' replace special characters:


result = System.Text.RegularExpressions.Regex.Replace(result, "&nbsp;", " ",
System.Text.RegularExpressions.RegexOptions.IgnoreCase)

result = System.Text.RegularExpressions.Regex.Replace(result, "&bull;", " * ",


System.Text.RegularExpressions.RegexOptions.IgnoreCase)
result = System.Text.RegularExpressions.Regex.Replace(result, "&lsaquo;", "<",
System.Text.RegularExpressions.RegexOptions.IgnoreCase)
result = System.Text.RegularExpressions.Regex.Replace(result, "&rsaquo;", ">",
System.Text.RegularExpressions.RegexOptions.IgnoreCase)
result = System.Text.RegularExpressions.Regex.Replace(result, "&trade;", "(tm)",
System.Text.RegularExpressions.RegexOptions.IgnoreCase)
result = System.Text.RegularExpressions.Regex.Replace(result, "&frasl;", "/",
System.Text.RegularExpressions.RegexOptions.IgnoreCase)
result = System.Text.RegularExpressions.Regex.Replace(result, "<", "<",
System.Text.RegularExpressions.RegexOptions.IgnoreCase)
result = System.Text.RegularExpressions.Regex.Replace(result, ">", ">",
System.Text.RegularExpressions.RegexOptions.IgnoreCase)
result = System.Text.RegularExpressions.Regex.Replace(result, "&copy;", "(c)",
System.Text.RegularExpressions.RegexOptions.IgnoreCase)
result = System.Text.RegularExpressions.Regex.Replace(result, "&reg;", "(r)",
System.Text.RegularExpressions.RegexOptions.IgnoreCase)
' Remove all others. More can be added, see
http://hotwired.lycos.com/webmonkey/reference/special_characters/
result = System.Text.RegularExpressions.Regex.Replace(result, "&(.{2,6});", String.Empty,
System.Text.RegularExpressions.RegexOptions.IgnoreCase)

' Thats it.


Return result
End Function
</script>

Page 12 of 13
Appendix D: Example iCAL file

BEGIN:VCALENDAR
PRODID:-//www.engsc.ac.uk//NONSGML Full Events Diary v1.0//EN
X-WR-CALNAME:Engineering Subject Centre Highlighted Events Diary
X-WR-TIMEZONE:Europe/London
X-WR-CALDESC:Events related to teaching and learning in Higher Education Engineering.
BEGIN:VEVENT
DTSTART;VALUE=DATE:20081210
DTEND;VALUE=DATE:20081213
UID:1394-20081210@engsc.ac.uk
SUMMARY:WPE--2008 Workshop on Philosophy and Engineering
DESCRIPTION:This is a multi--disciplinary conference for philosophers\, ethicists and engineers interested in the
philosophical and ethical issues surrounding engineering and technology.\nExtended abstracts are now being invited
on the following three 'demes': Philosophy\, Ethics and Reflections from Practitioners. The deadline for abstracts is 1
September 2008. The call for papers is available here: \n\nhttp://www.illigal.uiuc.edu/web/wpe/files/2008/08/wpe--
2008--extended--call--for--papers--081308.pdf\n\n For further information\, contact Natasha McCarthy on
natasha.mccarthy@raeng.org.uk or David Goldberg on
deg@uiuc.edu\n\n\nhttp://www.illigal.uiuc.edu/web/wpe/about/
LOCATION:Academy of Engineering\, Carlton House Terrace\, London
URL:http://www.illigal.uiuc.edu/web/wpe/about/
END:VEVENT
BEGIN:VEVENT
DTSTART;VALUE=DATE:20090121
DTEND;VALUE=DATE:20090122
UID:1459-20090121@engsc.ac.uk
SUMMARY:Peer Assessment
DESCRIPTION:Peer assessment has been proven over many years to be an effective activity to enhance learning.
Peer assessment is the process by which students provide formative or summative feedback to fellow students
enabling all involved to reflect and build on their knowledge and understanding. Technology can also be used to
support peer assessment\, especially for large student cohorts.\n \nThis event\, jointly organised with the Engineering
Subject Centre and the WebPA Project\, will introduce participants to the benefits of peer assessment from a key
researcher in this field and hear about how the WebPA project offers a technological solution for supporting peer
assessment.\nhttp://www.heacademy.ac.uk/physsci/events/detail/2009/peer_assessment
LOCATION:Manchester Conference Centre\, Manchester\, UK
URL:http://www.heacademy.ac.uk/physsci/events/detail/2009/peer_assessment
END:VEVENT
BEGIN:VEVENT
DTSTART:20090325T090000Z
DTEND:20090325T163000Z
UID:1472-20090325@engsc.ac.uk
SUMMARY:IPR & Engineers in Sports and Creative Industries
DESCRIPTION:2009 is the European Year of Innovation and Creativity (http://create2009.europa.eu/) and\, in 2012\,
London hosts the Olympic and Para Olympic Games -- so we are particularly interested in how these issues affect
innovators and designers in the Sports and Creative industries.\n\nThe first two workshops were exciting and fruitful
encounters that produced the 'whorl' resource of materials -- www.engsc.ac.uk/resources/ipminiproj/index.asp. It is
invaluable for anyone looking for ideas how to introduce IPR concepts to IPR creators. \n\nThe third workshop will be
attended by academics\, manufacturers\, practitioners\, policy makers\, entrepreneurs\, tech transfer officers and
some graduate students.\n\nIt will consider the significance of IPRs generated by engineering\, science and
technology specifically in the Sports and Creative industries\, and how it can be integrated into the curriculum.
\n\nWe are aware that it is still far from the norm for career entry scientists\, technologists or engineers to graduate
with an awareness of IPRs and their significance. Papers will explore whether that situation should be changed? If
so\, why? If so\, how? \n\nThis event is funded by the Higher Academy Engineering Subject Centre.\n\nIf you would
like to present a paper\, please contact Emily Cieciura on 01202 965197 or email
ecieciura@bournemouth.ac.uk\nhttp://www.cippm.org.uk/
LOCATION:The UK Intellectual Property Office\, Harmsworth House\, London EC4Y 8DP
URL:http://www.cippm.org.uk/
END:VEVENT
END:VCALENDAR

Page 13 of 13

You might also like