The Tales of Xcri-Cap

One of the first projects in my new job here at Edge Hill was JISC’s XCRI-CAP. Where would we be without acronyms? I was thoroughly pleased to have some new ones. Here’s the definitions:

  • JISC – a company that pushes innovative digital technology into UK education
  • XCRI-CAP – eXchanging Course Related Information, Course Advertising Profile. It’s a UK standard to describe course information for marketing.

JISC’s goal with XCRI-CAP is to share course information with the organisations who publish it, such as

Xcri - eXchanging Course Related Information




We’re making a feed for our Health CPD courses in the XCRI format so prospective students can find the course they’re looking for.

We moved all our health courses onto WordPress – our CMS (Content Management System) for most of our course information now. It was a good clean break, as we got to redesign the information’s structure to fit the XCRI specification. With the health courses in the CMS, we made the XCRI feed. It passes the course information to the feed aggregators so they can share the information.

Here’s a little information about each phase:

Database Mapping

This involved translating the old database content into the new xcri fields, where possible, and retaining the other useful information. We used the opportunity to strip out any useless information.

Database Mapping

This was the ‘get out your spreadsheet and be very thorough’ phase. It was pretty important because the information had to be labelled right so websites could understand it and use it properly.

We continued to the content management system…

Built a new Content Management System (CMS)

We actually extended WordPress, the CMS we use for most of our courses, by making a plugin that saves the health CPD modules. WordPress makes it fairly easy to add new functionality by providing hooks you can latch onto to adapt the software – basically slots to inject your customisations in.

Using WordPress’s custom post types we added courses and presentations to the CMS, and customised the admin area with the right input boxes. A presentation is a living instance of a course – for example, on the Tissue Viability course the Feb 2012 intake and July 2012 intake are different presentations.

WordPress makes it quite easy to add functionality by using existing plugins. We wanted more precise control over the admin page, so we did some of the building ourselves.

Customised WordPress admin menu

Once the CMS was done we transferred the course information into it.

 Built new web pages

We made a page template that displays an individual course’s information.

Front end website page template

We’ve still got some work to do on the template, like adding side navigation that links to similar courses.

Making the feed

We built an example feed that holds dummy information first.  We passed this through the Xcri 1.2 validator to make sure it was right. Eventually it stopped telling us we had made massive human errors, so the feed was right. Here’s the static version:

Static Xcri Feed

We made the real feed by passing the course information into this template from database.

And that’s where we are so far. Its nearly finished, and hopefully will make it much easier for people to find the right course.

Creole on PHP 5.2.4 with MSSQL

Working in a University or any organization generally leaves you supporting a lot of old code, on even older systems. As part of our web services infrastructure virtualisation project I’ve been bringing a lot of old code on to new systems. As can be seen when I got PHP 5.2.4 running on Ubuntu 12.04 LTS Precise.

As it turns out, our code wasn’t running so smoothly on PHP 5.2.4 as Arthur Koziel points out there is a problem with Creole and PHP 5.2.4. While we didn’t have the exact same problem, his post highlighted where it could be fixed.

Our problem was that we have a third party product using a Microsoft SQL database. It either always had, or just started to spit out date time values in the following format: Nov 14 2012 07:30:00:000PM note the non standard specification of microseconds. (Not sure which way around the problem occurred because we upgraded a month or so ago, but only just got a report of the problem.)

PHP’s strtotime really doesn’t like that format, and I can see why, horrible MSSQL!

I saw that I could fix this in creole/drivers/mssql/MSSQLResultSet.php by providing an alternate getTimestamp function and using a bit of strptime and sprintf magic. Below is the code I used to fix it. This might not be the most elegant solution, but it works!

* @see ResultSet::getTimestamp()
public function getTimestamp($column, $format = 'Y-m-d H:i:s')
$idx = (is_int($column) ? $column - 1 : $column);
if (!array_key_exists($idx, $this->fields)) { throw new SQLException("Invalid resultset column: " . $column); }
if ($this->fields[$idx] === null) { return null; }

$ts = strtotime($this->fields[$idx]);
if ($ts === -1 || $ts === false) { // in PHP 5.1 return value changes to FALSE
// in PHP 5.2.4 this no longer works, MSSQL provides date time as
// Nov 14 2012 07:30:00:000PM
$tsUgly = strptime($this->fields[$idx], '%b %d %Y %I:%M:%S:000%p');
$tsNicer = sprintf('%04d-%02d-%02d %02d:%02d:%02d',
$tsUgly['tm_year'] + 1900, // This will be years since 1900, so we need to add 1900.
$tsUgly['tm_mon'] + 1, // This will be the month 0-11, so we add one.
$ts = strtotime($tsNicer);
if ($ts === -1 || $ts === false) { // in PHP 5.1 return value changes to FALSE
throw new SQLException("Unable to convert value at column " . $column . " to timestamp: " . $this->fields[$idx]);
if ($format === null) {
return $ts;
if (strpos($format, '%') !== false) {
return strftime($format, $ts);
} else {
return date($format, $ts);

I hope that helps anyone else out there maintaining old code on newer systems. If anything it’ll help me if I come across a similar problem again!

Steve Daniels