{ Repost from my personal blog @ https://blog.codezero.xyz/generate-xcal-calendar-in-python }
“xCal”, is an XML format for iCalendar data.
The iCalendar data format (RFC5545) is a widely deployed interchange format for calendaring and scheduling data.
A Sample xCal document
<?xml version="1.0" encoding="utf-8"?> <iCalendar xmlns:xCal="urn:ietf:params:xml:ns:xcal"> <vcalendar> <version>2.0</version> <prodid>-//Pentabarf//Schedule 1.0//EN</prodid> <x-wr-caldesc>FOSDEM 2016</x-wr-caldesc> <x-wr-calname>Schedule for events at FOSDEM 2016</x-wr-calname> <vevent> <method>PUBLISH</method> <uid>123e4567-e89b-12d3-a456-426655440000</uid> <dtstart>20160131T090000</dtstart> <dtend>20160131T091000</dtend> <duration>00:10:00:00</duration> <summary>Introduction to the SDR Track- Speakers, Topics, Algorithm</summary> <description><p>The opening talk for the SDR devroom at FOSDEM 2016.</p></description> <class>PUBLIC</class> <status>CONFIRMED</status> <categories>Software Defined Radio</categories> <url>https:/fosdem.org/2016/schedule/event/sdrintro/</url> <location>AW1.125</location> <attendee>Martin Braun</attendee> </vevent> </vcalendar> </iCalendar>
Each event/session will be in a seperate vevent
block. Each speaker/attendee of an event/session will be in an attendee
block inside a vevent
block.
Some important elements are:
version
– Has the version of the iCalendar dataprodid
– Contains the name of the application/generator that generated this documentx-wr-caldesc
– A descriptive name for this calendarx-wr-calname
– A description of the calendar
The structure and keywords used in xCal are the same as those used in the iCal format. To generate the XML document, we’ll be using python’s ElementTree
XML API that is part of the Python standard library.
We’ll be using two main classes of the ElementTree API:
Element
– used to create a standard node. (Used for the root node)SubElement
– used to create a sub element and attache the new node to a parent
Let’s start with the root iCalendar
node and set the required attributes.
from xml.etree.ElementTree import Element, SubElement, tostring i_calendar_node = Element('iCalendar') i_calendar_node.set('xmlns:xCal', 'urn:ietf:params:xml:ns:xcal')
Now, to add the vcalendar
node to the iCalendar
node.
v_calendar_node = SubElement(i_calendar_node, 'vcalendar')
Let’s add the other aspects of the calendar to the vcalendar
node as separate sub nodes.
version_node = SubElement(v_calendar_node, 'version') version_node.text = '2.0' prod_id_node = SubElement(v_calendar_node, 'prodid') prod_id_node.text = '-//fossasia//open-event//EN' cal_desc_node = SubElement(v_calendar_node, 'x-wr-caldesc') cal_desc_node.text = "Calendar" cal_name_node = SubElement(v_calendar_node, 'x-wr-calname') cal_name_node.text = "Schedule for sessions"
Now, we have added information about our calendar. Now to add the actual events to the calendar. Each event would be a vevent
node, a child of vcalendar
node. We can loop through all our available event/sessions and add them to the calendar.
for session in sessions: v_event_node = SubElement(v_calendar_node, 'vevent') uid_node = SubElement(v_event_node, 'uid') uid_node.text = str(session.id) dtstart_node = SubElement(v_event_node, 'dtstart') dtstart_node.text = session.start_time.isoformat() dtend_node = SubElement(v_event_node, 'dtend') dtend_node.text = tz.localize(session.end_time).isoformat() duration_node = SubElement(v_event_node, 'duration') duration_node.text = "00:30" summary_node = SubElement(v_event_node, 'summary') summary_node.text = session.title description_node = SubElement(v_event_node, 'description') description_node.text = session.short_abstract class_node = SubElement(v_event_node, 'class') class_node.text = 'PUBLIC' status_node = SubElement(v_event_node, 'status') status_node.text = 'CONFIRMED' categories_node = SubElement(v_event_node, 'categories') categories_node.text = session.session_type.name url_node = SubElement(v_event_node, 'url') url_node.text = "https://some.conf/event/" + str(session.id) location_node = SubElement(v_event_node, 'location') location_node.text = session.microlocation.name for speaker in session.speakers: attendee_node = SubElement(v_event_node, 'attendee') attendee_node.text = speaker.name
Please note that all the timings in the XML Document must comply with ISO 8601 and must have the date+time+timezone. Example: 2007-04-05T12:30-02:00
.
We’re still not done yet. We now have the XML document as an Element
object. But we’ll be needing it as a string to either store it somewhere or display it.
The document can be converted to a string by using the ElementTree
API’s tostring
helper method and passing the root node.
xml_as_string = tostring(i_calendar_node)
And that’s it. You now have a proper XML document representing your events.