Convert xml2ics.pl to ics.xsl

* Reduces build time by 30%
* Remove perl and libxml-dom-perl dependency
* Improved date/time handling
* Improved text formating
This commit is contained in:
David Bartley 2008-02-02 23:00:50 -05:00
parent 5b5b65648f
commit 576edd6642
4 changed files with 119 additions and 146 deletions

View File

@ -33,7 +33,7 @@ $(OUTDIR)%.atom: %.xml xsl/atom.xsl
$(XSLTPROC) $< $(ROOT)/xsl/atom.xsl $@ $(XSLTARGS)
$(OUTDIR)%.ics: %.xml
perl scripts/xml2ics.pl $< > $@
$(XSLTPROC) $< $(ROOT)/xsl/ics.xsl $@ $(XSLTARGS)
$(OUTDIR)%.html: %.html
cp -f $< $@

View File

@ -1,130 +0,0 @@
#!/usr/bin/perl
use XML::DOM;
use strict;
# get the first element under a node of the given tag
# @param node: node under which to look for elements
# @param tag: the tage to look for
# @return: first element under node with the given tag
sub subvalue($$)
{
my ($class, $tag) = @_;
return value($class->getElementsByTagName($tag)->item(0));
}
# get the node value of the first child of a given node
# @param node: whose child to use
# @return: node value of given node's first child
sub value($)
{
my ($class) = @_;
if (undef == $class) { return undef; }
my $child = $class->getFirstChild();
if (undef == $child) {
return undef;
}
return $child->getNodeValue();
}
print <<END_OF_FILE;
BEGIN:VCALENDAR
VERSION:2.0
X-WR-CALNAME:University of Waterloo Computer Science Club
PRODID:-//Apple Computer\, Inc//iCal 2.0//EN
X-WR-RELCALID:3359A191-B19E-4B53-BADC-DFC084FC51C9
X-WR-TIMEZONE:Canada/Eastern
CALSCALE:GREGORIAN
METHOD:PUBLISH
BEGIN:VTIMEZONE
TZID:Canada/Eastern
LAST-MODIFIED:20060912T200739Z
BEGIN:DAYLIGHT
DTSTART:20060301T070000
TZOFFSETTO:-0400
TZOFFSETFROM:+0000
TZNAME:EDT
END:DAYLIGHT
BEGIN:STANDARD
DTSTART:20061029T020000
TZOFFSETTO:-0500
TZOFFSETFROM:-0400
TZNAME:EST
END:STANDARD
BEGIN:DAYLIGHT
DTSTART:20070311T010000
TZOFFSETTO:-0400
TZOFFSETFROM:-0500
TZNAME:EDT
END:DAYLIGHT
END:VTIMEZONE
END_OF_FILE
my $parser = XML::DOM::Parser->new();
my $doc = $parser->parsefile($ARGV[0]);
my @events = $doc->getElementsByTagName("eventitem");
foreach my $event (@events) {
my $date = $event->getAttribute("date");
my $time = $event->getAttribute("time");
my $talk_title = $event->getAttribute("title");
$talk_title =~ s/[:;,]//g;
my $room = $event->getAttribute("room");
my $short = subvalue($event, "short");
$short =~ s/[:;,]//g;
my $abstract = $event->getElementsByTagName("abstract")->item(0)->toString();
my $ical_date = `date -d"$date" +%Y%m%d`;
chomp $ical_date;
my ($ical_start, $ical_end);
if ($time =~ /(.*)-(.*)/) {
$ical_start = ical_time($1);
$ical_end = ical_time($2);
} else {
$ical_start = ical_time($time);
$ical_end = ical_time("$time + 1 hour");
}
$abstract =~ s/<abstract>//;
$abstract =~ s/<\/abstract>//;
$abstract =~ s/\n/ /sg;
my $ical_abstract = "\"$abstract\"";
sub ical_time {
my ($ds) = @_;
my $d = `date -d"$ds" +\%H\%M\%S`;
chomp $d;
return $d;
}
print <<END_OF_EVENT;
BEGIN:VEVENT
LOCATION:University of Waterloo - $room
DTSTAMP:20060912T200708Z
UID:${ical_date}T${ical_start}\@csclub.uwaterloo.ca
SEQUENCE:11
DTSTART;TZID=Canada/Eastern:${ical_date}T${ical_start}
DTEND;TZID=Canada/Eastern:${ical_date}T${ical_end}
SUMMARY:<a href=http://csclub.uwaterloo.ca>$talk_title</a> -- $short
DESCRIPTION:$ical_abstract
END:VEVENT
END_OF_EVENT
}
print "END:VCALENDAR\n";

View File

@ -1,5 +1,5 @@
#!/usr/bin/python
import os, sys, urllib, libxml2, libxslt, ldap, time
import os, sys, urllib, libxml2, libxslt, ldap, time, datetime, re
#
# globals
@ -24,6 +24,12 @@ cscPositions = {
}
cscYesNo = { True : 'yes', False : 'no' }
def xslArgToString(arg):
if type(arg) == type([]):
return libxml2.xmlNode(arg[0]).getContent()
else:
return arg
#
# cscLdapConnect
#
@ -35,29 +41,27 @@ def cscLdapConnect():
#
# csc:encode-for-uri
#
def cscEncodeForUri(ctx, arg):
if type(arg) == type([]):
arg = libxml2.xmlNode(arg[0]).getContent()
return urllib.quote(arg)
def cscEncodeForUri(ctx, uri):
uri = xslArgToString(uri)
return urllib.quote(uri)
#
# csc:term
#
def cscTerm(ctx, arg):
if type(arg) == type([]):
arg = libxml2.xmlNode(arg[0]).getContent()
def cscTerm(ctx, date):
date = xslArgToString(date)
try:
[year, month, day] = arg.split("-")
[year, month, day] = date.split("-")
term = (int(month) - 1) / 4
return cscTerms[term] + " " + year
except:
print "Invalid term '%s'" % arg
print "Invalid date '%s'" % date
raise
#
# csc:member-list
#
def cscMemberList(ctx, arg):
def cscMemberList(ctx, _):
try:
if cscLdap == None:
cscLdapConnect()
@ -83,7 +87,7 @@ def cscMemberList(ctx, arg):
#
# csc:position-list
#
def cscPositionList(ctx, arg):
def cscPositionList(ctx, _):
try:
if cscLdap == None:
cscLdapConnect()
@ -119,12 +123,46 @@ def cscPositionList(ctx, arg):
print e
raise
#
# csc:ical-datetime
#
def cscIcalDatetime(ctx, date, time, addmin = "0"):
date = xslArgToString(date)
time = xslArgToString(time)
addmin = int(xslArgToString(addmin))
r = re.search("(\d*)-(\d*)-(\d*)", date)
year, month, day = 0, 0, 0
if r != None:
year, month, day = (int(i) for i in r.groups())
r = re.search("(\d*):(\d*)\s*([apAP])", time)
hour, minute = (0, 0)
if r != None:
hour, minute = (int(i) for i in r.groups()[:2])
if r.group(3) in 'pP':
hour += 12
dt = datetime.datetime(year, month, day, hour, minute)
dt += datetime.timedelta(0, 0, 0, 0, addmin)
return dt.strftime("%Y%m%dT%H%M%S")
#
# csc:ical-escape
#
def cscIcalEscape(ctx, str):
str = xslArgToString(str)
str = str.replace("\n", " ")
str = str.replace(":", "")
str = str.replace(";", "")
str = str.replace(",", "")
str = re.sub("\s+", " ", str)
str = re.sub("^\s+", "", str)
str = re.sub("\s+$", "", str)
return str
#
# csc:email
#
def cscEmail(ctx, arg):
if type(arg) == type([]):
str = libxml2.xmlNode(arg[0]).getContent()
def cscEmail(ctx, email):
email = xslArgToString(email)
return "_EMAIL_TODO_"
#
@ -156,6 +194,8 @@ try:
libxslt.registerExtModuleFunction("term", cscUri, cscTerm)
libxslt.registerExtModuleFunction("member-list", cscUri, cscMemberList)
libxslt.registerExtModuleFunction("position-list", cscUri, cscPositionList)
libxslt.registerExtModuleFunction("ical-datetime", cscUri, cscIcalDatetime)
libxslt.registerExtModuleFunction("ical-escape", cscUri, cscIcalEscape)
libxslt.registerExtModuleFunction("email", cscUri, cscEmail)
# parse xml/xslt and apply style-sheet
@ -166,4 +206,5 @@ try:
ret = style.saveResultToFilename(outFile, res, 0)
except Exception, e:
print e
sys.exit(1)

62
xsl/ics.xsl Normal file
View File

@ -0,0 +1,62 @@
<xsl:stylesheet version="1.1"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:csc="http://csclub.uwaterloo.ca/xsltproc"
xmlns="http://www.w3.org/1999/xhtml"
exclude-result-prefixes="csc">
<xsl:output method="text" encoding="ISO-8859-1" />
<xsl:template match="//eventdefs">BEGIN:VCALENDAR
VERSION:2.0
X-WR-CALNAME:University of Waterloo Computer Science Club
PRODID:-//Apple Computer, Inc//iCal 2.0//EN
X-WR-RELCALID:3359A191-B19E-4B53-BADC-DFC084FC51C9
X-WR-TIMEZONE:Canada/Eastern
CALSCALE:GREGORIAN
METHOD:PUBLISH
BEGIN:VTIMEZONE
TZID:Canada/Eastern
LAST-MODIFIED:20060912T200739Z
BEGIN:DAYLIGHT
DTSTART:20060301T070000
TZOFFSETTO:-0400
TZOFFSETFROM:+0000
TZNAME:EDT
END:DAYLIGHT
BEGIN:STANDARD
DTSTART:20061029T020000
TZOFFSETTO:-0500
TZOFFSETFROM:-0400
TZNAME:EST
END:STANDARD
BEGIN:DAYLIGHT
DTSTART:20070311T010000
TZOFFSETTO:-0400
TZOFFSETFROM:-0500
TZNAME:EDT
END:DAYLIGHT
END:VTIMEZONE
<xsl:for-each select="eventitem"><xsl:call-template name="eventitem" /></xsl:for-each>
END:VCALENDAR
</xsl:template>
<xsl:template name="eventitem">
<xsl:variable name="room" select="@room" />
<xsl:variable name="start" select="csc:ical-datetime(@date, @time)" />
<xsl:variable name="end" select="csc:ical-datetime(@date, @time, 60)" />
<xsl:variable name="title" select="csc:ical-escape(@title)" />
<xsl:variable name="short" select="csc:ical-escape(string(short))" />
<xsl:variable name="abstract" select="csc:ical-escape(string(abstract))" />
BEGIN:VEVENT
LOCATION:University of Waterloo - <xsl:value-of select="$room" />
DTSTAMP:20060912T200708Z
UID:<xsl:value-of select="$start" />@csclub.uwaterloo.ca
SEQUENCE:11
DTSTART;TZID=Canada/Eastern:<xsl:value-of select="$start" />
DTEND;TZID=Canada/Eastern:<xsl:value-of select="$end" />
SUMMARY:<xsl:value-of select="$title" /><xsl:if test="$short != ''"> -- <xsl:value-of select="$short" /></xsl:if>
DESCRIPTION:<xsl:value-of select="$abstract" />
END:VEVENT
</xsl:template>
</xsl:stylesheet>