Skip to content
Mike Angstadt edited this page Aug 23, 2018 · 5 revisions

iCalendar data can be encoded in XML. This format is called xCal. The xCal specification is defined in RFC 6321.

Below is an example of an xCal document.

<?xml version="1.0" encoding="utf-8"?>
<icalendar xmlns="urn:ietf:params:xml:ns:icalendar-2.0">
  <vcalendar>
    <properties>
      <version>
        <text>2.0</text>
      </version>
      <prodid>
        <text>-//Microsoft Corporation//Outlook 14.0 MIMEDIR//EN</text>
      </prodid>
    </properties>
    <components>
      <vevent>
        <properties>
          <uid>
            <text>d6d88f2e50080b9602da53dac1102762</text>
          </uid>
          <dtstamp>
            <date-time>2013-06-01T08:00:00Z</date-time>
          </dtstamp>
          <summary>
            <parameters>
              <language>
                <text>en-us</text>
              </language>
            </parameters>
            <text>Team Meeting</text>
          </summary>
          <dtstart>
            <date-time>2013-06-10T12:00:00Z</date-time>
          </dtstart>
          <duration>
            <duration>PT1H</duration>
          </duration>
          <rrule>
            <recur>
              <freq>WEEKLY</freq>
              <interval>2</interval>
            </recur>
          </rrule>
        </properties>
      </vevent>
    </components>
  </vcalendar>
</icalendar>

1 Reading XML-encoded iCalendar data

The XCalReader class handles the parsing of XML-encoded iCalendar data. The data is read in a streaming fashion, meaning it parses the data as it is read off the wire. This results in a smaller memory footprint than other approaches.

XCalReader automatically takes timezone data into account by parsing date/time values according to their assigned VTIMEZONE definition. See the Timezones page for more information on working with timezones.

1.1.1 Important methods

readNext()
Parses and returns the next ICalendar object in the data stream. The method returns null when the end of stream has been reached.

getWarnings()
Returns any problems the parser encountered while parsing the ICalendar object that was last returned by readNext(). Examples of things that could cause warnings are: unparseable property values (such as malformed date values).

close()
As with all I/O operations, it's important to call the close() method when you are done with the XCalReader object in order to properly close the input stream.

Please see the Javadocs for a complete listing of all the methods.

1.1.2 Example

The example below outputs the start times and summaries of each event in an XML-encoded iCalendar data stream.

Note that, when outputting the start dates, the DateFormat object is not configured with a timezone. Therefore, the dates will be displayed in the user's local timezone. For example, if a date/time value has a time of 13:00 UTC, and the user's local timezone is 5 hours behind UTC, the time will be displayed as "08:00".

File file = new File("events.xml");
XCalReader reader = new XCalReader(file);
try {
  ICalendar ical;
  DateFormat df = new SimpleDateFormat("MM/dd/yyyy HH:mm");
  while ((ical = reader.readNext()) != null) {
    for (VEvent event : ical.getEvents()) {
      DateStart dateStart = event.getDateStart();
      String dateStartStr = (dateStart == null) ? null : df.format(dateStart.getValue());

      Summary summary = event.getSummary();
      String summaryStr = (summary == null) ? null : summary.getValue();

      if (summaryStr != null && dateStartStr != null) {
        System.out.println(dateStartStr + ": " + summaryStr);
        continue;
      }

      if (summaryStr != null){
        System.out.println(summaryStr);
        continue;
      }

      if (dateStartStr != null){
        System.out.println(dateStartStr);
        continue;
      }
    }
  }
} finally {
  reader.close();
}

Alternatively, the XCalDocument class can be used to read XML-encoded iCalendar data. This class is essentially a wrapper for a org.w3c.dom.Document object, providing methods that read and write ICalendar objects from/to the DOM tree.

1.2.1 Important methods

getICalendars()
Parses all ICalendar objects that exist inside of the DOM tree.

getDocument()
Returns the wrapped Document object, giving you full control over the XML data.

Please see the Javadocs for a complete listing of all the methods.

1.2.2 Example

The example below reads XML-encoded iCalendar data from the Internet and outputs the start times and summaries of each event.

InputStream in = new URL("http://example.com/events.xml").openStream();
XCalDocument document;
try {
  document = new XCalDocument(in);
} finally {
  in.close();
}

List<ICalendar> icals = document.getICalendars();
DateFormat df = new SimpleDateFormat("MM/dd/yyyy HH:mm");
for (ICalendar ical : icals){
  for (VEvent event : ical.getEvents()) {
    DateStart dateStart = event.getDateStart();
    String dateStartStr = (dateStart == null) ? null : df.format(dateStart.getValue());

    Summary summary = event.getSummary();
    String summaryStr = (summary == null) ? null : summary.getValue();

    if (summaryStr != null && dateStartStr != null) {
      System.out.println(dateStartStr + ": " + summaryStr);
      continue;
    }

    if (summaryStr != null){
      System.out.println(summaryStr);
      continue;
    }

    if (dateStartStr != null){
      System.out.println(dateStartStr);
      continue;
    }
  }
}

1.3 A note about unparseable property values

If a property's value cannot be parsed, or if the property's XML element does not have the correct child elements, the property is parsed as an Xml property and a warning is logged. Xml properties store the raw XML of the property that could not be parsed. The code below demonstrates this:

String xml =
"<icalendar xmlns=\"urn:ietf:params:xml:ns:icalendar-2.0\">" +
  "<vcalendar>" +
    "<properties>" +
      "<version>" +
        "<text>2.0</text>" +
      "</version>" +
    "</properties>" +
    "<components>" +
      "<vevent>" +
        "<properties>" +
          "<summary>" +
            "<text>Party at my place.</text>" +
          "</summary>" +
          "<dtstart>" +
            "<date-time>Come over whenever, dude.</date-time>" +
          "</dtstart>" +
        "</properties>" +
      "</vevent>" +
    "</components>" +
  "</vcalendar>" +
"</icalendar>";

XCalReader reader = new XCalReader(xml);
ICalendar ical = reader.readNext();

List<String> warnings = reader.getWarnings();
System.out.println("Warnings: " + warnings);

VEvent event = ical.getEvents().get(0);
System.out.println("DTSTART property: " + event.getDateStart());

Xml prop = event.getProperties(Xml.class).get(0);
System.out.println("XML property: " + XmlUtils.toString(prop.getValue()));

reader.close();

The above code produces the following output:

Warnings: [dtstart property: (16) Property could not be unmarshalled.  Unmarshalling as an XML property instead.  Reason: (17) Could not parse date-time value.]
DTSTART property: null
XML property: <?xml version="1.0" encoding="UTF-8"?><dtstart xmlns="urn:ietf:params:xml:ns:icalendar-2.0"><date-time>Come over whenever, dude.</date-time></dtstart>

2 Writing XML-encoded iCalendar data

The XCalWriter class handles the creation of XML-encoded iCalendar data.

By default, XCalWriter automatically formats all date/time values in UTC time, but this can be changed. See the Timezones page for more information on working with timezones.

2.1.1 Important methods

write()
Writes the contents of an ICalendar object to the data stream.

close()
As with all I/O operations, it's important to call the close() method when you are done with the XCalWriter object in order to properly close the output stream. It's especially important for XCalWriter because it must write the proper XML closing tags to properly close the XML document.

Please see the Javadocs for a complete listing of all the methods.

2.1.2 Example

The example below writes a list of ICalendar objects to an XML file. The output will be pretty-printed, using an indentation string of 2 spaces.

List<ICalendar> icals = ...
File file = new File("events.xml");
XCalWriter writer = new XCalWriter(file, 2);
try {
  for (ICalendar ical : icals) {
    writer.write(ical);
  }
} finally {
  writer.close();
}

Alternatively, the XCalDocument class can be used to write XML-encoded iCalendar data. This class is essentially a wrapper for a org.w3c.dom.Document object, providing methods that read and write ICalendar objects from/to the DOM tree.

2.2.1 Important methods

add()
Adds the contents of an ICalendar object to the XML DOM tree.

getDocument()
Returns the wrapped Document object, giving you full control over the XML data.

write()
Outputs the XML DOM tree to a string or output stream. This method is overloaded to allow you to customize the write process (for example, by specifying the number of indentation spaces to use to pretty-print the XML).

Please see the Javadocs for a complete listing of all the methods.

2.2.2 Example

The example below writes a list of ICalendar objects to an XML file. The output will be pretty-printed, using an indentation string of 2 spaces.

List<ICalendar> icals = ...
XCalDocument document = new XCalDocument();
for (ICalendar ical : icals) {
  document.add(ical);
}

File file = new File("events.xml");
document.write(file, 2);