Archive for the ‘Technical’ Category

“The Magic” – restructuring the EAD to RDF XSLT transform

Wednesday, October 12th, 2011

By Pete Johnston

In a previous post I described how I had used an XSLT transform to generate RDF/XML from the EAD XML representation of the Mass Observation Archive catalogue exported from the CALM archival data management system. My approach was to take the XSLT I’d created within the LOCAH project to process the Archives Hub EAD data as a starting point, and to amend and extend it to processs the MOA data.

In that post, I suggested that there were some aspects of the transformation process which were more “general” and based on structural conventions that were common to, maybe not all, but a large subset of EAD documents, while others were more specific/”local” to the particular content of the MOA data, and that it might be possible/useful to try to separate out these different parts of the processing to make it easier to apply only the general/generic processing and to “swap in” different “local” processing as required for different input datasets.

While thinking about this, I broke things down further:

  • Processing based on generic EAD structures which are used consistently across all EAD documents
  • Processing based on EAD structures which are used consistently across some fairly broad category of EAD documents. I’m thinking here of something like the set of EAD documents which follow the Archives Hub data entry guidelines, or maybe the set of EAD documents generated by export from CALM systems (I say “maybe” here because I don’t have enough experience to know how uniform this process is, and how much variation is possible)
  • Processing where the technique might be generally applied, but “local” configuration or parameterisation is required. For example, the keyword lookup approach I described in my earlier post might be applied to a range of different inputs, but one might want to look up a different set of keywords for the catalogues of the archives of 19th century industrialists on the one hand and those of late twentieth century poets on the other – either simply for the sake of efficiency (e.g. there’s no point in searching for “Hitler” in the 19th century industrialists’ case) or because one wishes to map a single “keyword” to a different “real world entity” in each case.
  • Processing which is very specific to the structure or content of the input data. For example, for the MOA case, the transform included some processing based on specific EAD unitid content (e.g. “If unitid starts with “SxMOA1/2/”, then extract a “topic name” from unittitle“. If this processing was applied to a different set of inputs, it might have no effect (because the test is not satisfied by any unitid) or it might have an unintended effect (if the test is satisfied and the processing is applied to a unittitle not constructed in that way – rather unlikely given the specific nature of the test in this case but still possible)

The previous version of the MOA XSLT used a single transform. I’ve tried to restructure it slightly to reflect these distinctions (or at least the last three of the four). In this new version, there are now three XSLT transforms:

  1. ead2rdf.xslt
  2. lookup-ead2rdf.xsl
  3. moa-ead2rdf.xsl

The first of these (ead2rdf.xsl) is a slightly “stripped down” version of the XSLT from the LOCAH project, which removes processing specific to the Hub data (e.g. the use of particular conventions to mark up controlaccess terms), and can be run stand-alone. Given the nature of the EAD format, I hesitate to say it is generic to all EAD documents: really, its design was driven by the structures of the particular documents I’ve had at hand, and it’s probably still more in the second category in my list above, rather than being completely “generic”. So for example, it makes the assumption that the agency that maintains the finding aid is the same as the agency that provides access to the archive, a restriction which is not required by EAD itself. But it does exclude the name/keyword lookups and some processing which was specific to characteristics of the Archives Hub data and the MOA data.

The second transform (lookup-ead2rdf.xsl) imports the first, and includes the lookup processing. The URIs of the two “lookup tables” (simple XML documents: see and for examples) are provided as parameters, so can be any URI, and different lookup files for different inputs can be provided at run-time.

The third XSLT (moa-ead2rdf.xsl) imports the second, and includes the MOA-specific processing. So running moa-ead2rdf.xsl provides the generic processing + the name/keyword lookups + the MOA-specific processing.

And if someone has a different set of EAD inputs where they want to apply some quite different rules, then they can create anotherarchive-ead2rdf.xsl which imports either the first XSLT above (if they don’t want name/keyword lookups) or the second (if they do want name/keyword lookups, for which they can also specify their own “lookup tables”).

I should emphasise that I did this as a fairly quick exercise to try to illustrate that it was possible to “modularise” the processing to separate out the “local” and the “general”. As I’ve suggested above, the separation I’ve made isn’t perfect and the base transform is probably not as “generic” as it might be. There are almost certainly more “elegant” and efficient ways of achieving the separation in XSLT. Nevertheless I found it a useful process to go through and I think it reflects some of the challenges of working with a format like EAD which combines “document-like” and “data-like” characteristics and allows a high level of structural variation.

Linking to LOCAH

Wednesday, October 12th, 2011

As readers of this blog will know, we followed closely in the footsteps of the LOCAH project and we are now linked to the Archives Hub dataset. Which is nice.

See as an example

Our other  external links are:

-DBpedia (for some places, people & organisations) e.g.

– Geonames (for some places) e.g.

– LCSH (for some concepts) e.g.

– VIAF (for some people) e.g.

Converting EAD data to RDF Linked Data

Monday, July 25th, 2011

In my last blog post I discussed how to setup our server to handle the URIs being created within our Linked Data, and said the next step was for us to turn our EAD/XML data from Calm in to RDF/XML Linked Data.

This is a big step, until now our process looked something like this: Export EAD data -> send it to someone else -> Magic -> Linked Data!

Pete Johnston provided us with details of the magic part. In essence much of the complexity is hidden in an XSLT script (XSLT is a language to process XML in to different schemas, such as here, or in to HTML and other formats). He’s blogged about some of the decisions and concepts that have gone in to it. However, here, we can treat it like a black box. It’s still magic, but we know how to use it.

Converting EAD to XSLT using XSLT and Saxon

We use the Saxon HE XSLT (Java) version to the do transformation. It’s simple to download and setup. The basic core step is very simple: run Saxon, passing it the name of the EAD/XML file and the XSLT file. An example command line looks like this:

java -jar 'saxon9he.jar' -s:ead/ -xsl:xslt/ead2rdf.xsl -o:rdf/ root=

And there you have it, your EAD data is now RDF!

Before the data is loaded in to the Talis Platform store, there’s a couple more things we do.

Triples and Turtle

The first is the conversion of the RDF/XML in to the alternative RDF format N-Triples (and also Turtle) using the Raptor RDF parser.

RDF can be written and presented in a number of ways. Probably the most common method is using XML, partly due to the XML language being so ubiquitous, however it is very verbose and can be difficult to read by us humans.

Not only is N-Triples considered easier to read. but each line contains a fully complete and self-contained Triple (a Triple contains a subject, predicate and object, mostly expressed as URIs). While it isn’t too much of an issue here, this allows us to split up the data in to smaller chunks/files which can be POSTED to the Talis Platform.

Talis Platform

The Talis Platform is a well established Triple Store (think of a SQL database but with three part triples rather than records and tables). While you can run your own Triple Store using software such as ARC2, the Talis Platform provides a stable, robust and quick solution.

You interact with the Platform with standard HTTP Requests; GET, POST, DELETE etc. However for simplicity an interactive command prompt front end has been developed in Python called Pynappl. This allows you to simply specify the store you wish to work with, authenticate, and then use commands such as ‘store filename.rdf’ to upload data.

A simple script can upload our data to the Platform, uploading each n-triple file created above.

The final step is to try our the Sparql interface at:

Here’s one to try:

?a ?b <>


To take our EAD from Calm and turn it in to Linked Data we used a XSLT script written by Pete Johnston, used Saxon to transform the EAD/XML in to RDF/XML using the XSLT script. Then we converted the RDF/XML to RDF/N-Triples using Raptor. And finally we used Pynappl to upload this to the Talis Platform.

The XSLT scripts mentioned here can be found at:

The RDF Linked Data is available for download, in addition to the SPARQL interface above:

My Thanks to Pete Johnston of Eduserv for providing the process (with documentation) described above.

This page has been translated into Spanish by Maria Ramos from

Setting up our URIs and the Talis Platform

Wednesday, July 13th, 2011

Time to set up our URIs and upload our data to one of our Talis Platform stores.

In a previous post we discussed which URIs to use. We settled on – we felt this should be stable, and allow for integration with other Special Collection records in the future (while not conflicting with other Library data).

We now needed those URIs to do something, at the moment they all just returned a 404 message (albeit a 404 message with a Rick  roll link).

As so often the case in this project this is where Pete Johnston came in. He had already set up the required code on his test server, and similar things had been put in place for the LOCAH project.

In total, all that is required is a few php/html files and a .htaccess file to handle rewrites (i.e. taking a URI and calling the script in question with the righthand bit of the URI as a parameter). The main script is an index.php file which on our server lives at www/data/archive/doc (which corresponds to

Along with these files were a few dependencies, PHP libraries: paget, moriarty and ARC.

However this code needs to access data from somewhere, and to do this we need to put our data in to our new shiny Talis Platform store…

Talis Platform

The second part of this work was to upload our data to the Talis Platform. Talis had kindly created to stores for us: massobservation and massobservation-dev1, as part of their Connect Commons scheme.

Pete ran a set of scripts he had developed to upload our data to the dev1 store. We’re currently installing these on our own server so we can do this ourselves, and we’ll report more on them soon.

So that was that, without much fuss, we now had our data in our publicly available, Sparql query-able, RDF store. There probably should have been champagne.

Back to our server

So with our data now in a RDF store, libraries installed on server, files copied and in place, config edited to point to our store, it was time to point a browser at one our URIs and start debugging the first error message (which once resolved will lead to the next error message, and so forth). But… for the first time in my life, it just worked. This never happens. It left me confused, I had set aside hours of my diary for endless frustrations and here it was working. I felt cheated. But, once over the shock, I (and you too) could visit examples such as this: (RDF/XML, JSON, Turtle)

Look! It’s our data… as Linked Data… live on the internet!

I would like to see become more than just the Mass Observation Archive, and with that in mind I created a front end for the top level URL:

This uses WordPress as the CMS (life’s to short to code the html/css files by hand).

For those interested, the .htaccess mod_rewrite looks like this:

<IfModule mod_rewrite.c>
RewriteEngine On
RewriteRule ^archive/id/(.*)$ /archive/doc/$1 [R=303,L]
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]

The rule for the URIs is at the top (simply redirecting archive/id/* to archive/doc/*) if this rule is ‘matched’ then processing ends and the rest of the rules are ingnored ( [L] ), otherwise process the standard WordPress rules.

Next steps… (for this strand of work)

Install scripts on our server so that we can:

  • take a file of EAD date from Calm and transform in to a file of RDF/XML
  • convert this to a set of N-Triples files (which are easier to upload to the Platform store as each statement/triple (or if you prefer, fieldname and field value from a record) is complete and able to standalone, so the data can be uploaded in stages without complications.
  • Upload the files to the store.

The data transformation

Monday, May 16th, 2011

by Pete Johnston

I’ve been working on a first attempt at processing the Encoded Archival Description (EAD) XML output provided by Karen from their CALM database in order to generate RDF data for the Mass Observation Archive. My starting point has been the work done within the LOCAH project, to which I’ve also been contributing, and which is also transforming EAD data into linked data.

I’m making use of the same general approach as that we’ve used within the LOCAH project, so as background to this post, it’s probably worth having a look at some of the relevant posts on the LOCAH blog and/or at the initial dataset they have just released.

The “workflow” for the SALDA/MOA case is similar to that described in the first part of this post, with an additional preliminary step of exporting data from the CALM database into the EAD XML format. And as I’ll explain further below, for the SALDA case, the “transform” step will also include a small element of what I was calling “enhancement” – the augmentation of the EAD content with some additional data.

We’re making use of (more or less – more on this also below) the same model of “things in the world” as that we’ve applied in the LOCAH project (see these three posts for details 1, 2, 3); the same patterns for URIs for identifying the individual “things” – within a University of Sussex URI-space, as Karen and Chris have discussed in recent posts here; and (more or less) the same RDF vocabularies for describing those “things”.

EAD and the LOCAH and SALDA EAD data

As I noted in the first of those posts over on the LOCAH blog the EAD format is, by design, a fairly “flexible” and “permissive” XML format. It was designed to accommodate the “encoding” of existing archival finding aids of various types and constructed by different cataloguing communities, some with practices and traditions which varied to a greater or lesser degree. EAD also allows for variation in the “level of detail” of markup that can be applied, from a focus on the identification of broad structural components to a more “fine-grained” identification of structures within the text of those components. As a result the structure of EAD XML documents can vary considerably from one instance to the next.

The LOCAH project is dealing with EAD data aggregated by the JISC Archives Hub service. This is data provided by multiple data providers, in some cases over an extended period of time, and sometimes using different data creation tools – and one of the challenges in LOCAH has been dealing with the variations across that body of data. SALDA, on the other hand, is dealing with data a single data source, under the control of a single data provider – the MOA data is actually exported from the CALM database in the form of a single EAD document, albeit quite a large one!

So while the LOCAH input data includes EAD documents using slightly different structural and content conventions, for SALDA, that structure is regular and predictable, and furthermore some element of “normalisation” of content is implemented through the rules and checks performed by the CALM database application.

So far, so good, then, in terms of making the MOA EAD data relatively straightforward to process.

Index Terms

The data creation guidelines for contributors to the Archives Hub recommend the provision of “index terms” or “access points” using the EAD controlaccess element – names of topics, persons, families, organisations, places, genres or functions, whose association with the archival resource is potentially useful for people searching the finding aid. Those names are (in principle, at least!) provided in a “standardised” form (i.e. either drawn from a specified “authority file” of names or constructed using a specified set of rules) so that two documents using the same authority file or the same rules should provide the same name in the same form. In the process of transforming EAD into RDF within the LOCAH project, the controlaccess element is a significant source of information about “things” associated with the archival resource. Below is a version of the graphical representation of the LOCAH model, taken from this post. Data about the entities circled in the lower part of the diagram is all derived from the LOCAH EAD controlaccess data.

In the MOA data, however, no controlaccess terms are provided. Talking this over with Karen and Chris recently, however, made it clear that there are some associations implicit in the MOA data, and there are some “hooks” in the data which can provide the basis for generating explicit associations in the RDF data. This is probably best illustrated through some concrete examples.

“Topic Collections”

One section of the Mass Observation Archive takes the form of a sequence of “Topic Collections”, in which documents of various types are grouped together by theme or subject, the name of which forms part of the title of a “series” within the section, i.e. the series have titles like:

  • TC1 Housing 1938-48
  • TC6 Conscientious Objection & Pacifism 1939-44
  • TC7 Happiness 1938

Although the titles are encoded in the EAD documents as unstructured text (as the content of the EAD unittitle element), the text has a consistent/predictable form of: code number, name of topic, date(s) of period of creation.

We can take advantage of this consistency in the transformation process and, with some fairly simple parsing of the text of the title, generate a description of a concept with its own URI and name/label (e.g. “Housing”, “Conscientious Objection & Pacifism” or “Happiness”), and a link between the archival resource and the concept. (For this case, the dates are provided explicitly elsewhere in the EAD document and already handled by the transformation process.)

Series by Place

Within one of the “Topic Collections” (on air raids), sets of reports are grouped by place, where the name of the place is used as the title of the “file”. So again, it is straightforward to generate a small chunk of data “about” the place with its own URI and name/label, and a link between the archival resource and the place.

In both this case and the “topic collections” case, we can also be quite specific about the nature of the relationship between the archival resource and the concept or place. In the LOCAH case, we’ve limited ourselves to making a very general “associated with” relationship between the archival resource and the controlaccess entity, on the grounds that the cataloguer may have made the association with the archival material based on many different “real world” relationships. For these cases in SALDA, we can be more specific, and say that the relationship is one of “aboutness”/has-as-topic, which can be expressed using the Dublin Core dcterms:subject property.

Directives by Date

Another section of the archive lists responses to “directives” (questionnaires) by date. In these cases the dates are not provided separately in the EAD data, but again the consistent form of the title makes it relatively straightforward to extract and present the dates explicitly in the RDF data.


Each of the above examples exploits some implicit structure in text content within the EAD document. A second approach we’ve applied is to scan the content of some EAD elements for words or phrases that can be mapped to specific entities (concepts, persons, organisations, places). In making this mapping, we’re really taking advantage of the fact that for the SALDA case we have a fairly well-defined context or scope, defined by the scope of the archival collection itself. So within that context, we can be reasonably confident that an occurrence of the word “Churchill” is a reference to the war-time Prime Minister, rather than to another member of his family, or a Cambridge college, or an Oxfordshire town.

Because this process involves matching to a set of known concepts/places/persons/organisations, and because it’s a relatively short list, I’ve taken advantage of this to extend the “lookup table” to include some URIs from DBpedia, Geonames and the Library of Congress LCSH dataset, which I use to construct owl:sameAs or skos:closeMatch/skos:exactMatch links to external resources as part of the transformation process.

“Multi-level description” and “Inheritance”

One of the general issues these approaches bring me back to is the question of “multi-level description” in archival description, and which I discussed briefly in a post on the LOCAH blog. Traditionally archival description advocates a “hierarchical” approach to resource description: a conceptualisation of an archival collection as having a “tree” structure single, with a finding aid document providing information about an aggregation of records, then about component subsets of records within that aggregation, and so on, sometimes down to the level of individual records but often stopping at the level of some component aggregation.

This “document-centric” approach carries with it an expectation that the description of some “lower level” unit of archival material is presented and interpreted “in the context of” those other “higher level” descriptions of other material. And this is reflected in a principle of “non-repetition” in archival cataloguing:

At the highest appropriate level, give information that is common to the component parts. Do not repeat information at a lower level of description that has already been given at a higher level.

There is some suggestion here of information of lower-level resources implicitly “inheriting” “common” characteristics from their “parent” resources – unless they are “overriden” in the description of the “lower-level” resource.

In practice, however, this “inheritance” is more applicable to some attributes than others: it may work for, say, the name of the holding repository, but it is less clear that it applies to cases such as the controlaccess “index terms”: it may be appropriate/useful to associate the name of a person with a collection as a whole, but it doesn’t necessarily follow that the person has an association with every single item within that collection.

The “linked data” approach is predicated on delivering information in the form of “bounded descriptions” made up of assertions “about” individual subject resources. So in transforming EAD data into an RDF dataset to support this, we’re faced with the question of how to deal with this “implicitly inherited” information: whether to construct assertions of relationships only for the resource for which they are explicitly present in the EAD document, or whether also to construct additional assertions for other “descendent” resources too, on the basis that this is making explicit information that is implicit in the EAD document.

In the LOCAH work, we’ve tended to take a fairly “conservative” approach to the “inheritance” question and worked on the basis that, in the RDF data the concept, person, place, etc named by a controlaccess term is associated only with the archival resource with which the term is associated in the EAD document.

For the SALDA/MOA data, I think an argument can be made – at least for some of the cases discussed above – for making such links for the “descendent” component resources too. For the “topic collections”, for example, it is a defining characteristic of the collection that each of the member resources has the named concept as topic. And a similar case might be made for the “place-based” series.

For the keyword-matching cases, an assumption that the association can be generalised to all the “descendent” resources would, I think, be more problematic.

The “foaf:focus question”

In the Archives Hub data that LOCAH is using, the controlaccess terms are (mostly at least) drawn from “authority files”. This is reflected in the LOCAH data model in a distinction between the “conceptualisation” of a person, organisation or place that is captured in a thesaurus entry or authority file record, as separate from the actual physical entity. So for the person/organisation/family/place cases, in the LOCAH transformation process, the presence of an EAD controlaccess term results in the generation of two URIs and two triples, the first expressing a relationship (locah:associatedWith) between archival resource and concept, and the second between concept and entity (person, organisation, place). This second relationship is expressed using a (recently introduced) property from the Friend of a Friend (FOAF) RDF vocabulary, foaf:focus.

For a concrete example from the LOCAH dataset, consider the case of the Sir Joseph Dalton Hooker collection, which is identified by the URI The description of that “Archival Resource” shows that the collection is “associated with” four other resources, identified by the following URIs:

If we look in turn at the descriptions of those resources, we see that they are all concepts (i.e. instances of the class skos:Concept) – even the second and third cases. And in those two cases the concept is the subject of a “foaf:focus” relationship with a further resource, of type Person and Organisation, respectively:

I’ve tried to depict this in the graph below. I’ve omitted the rdf:type arcs for conciseness, and relied on colour to indicate resource type (blue = Archival resource; white = Concept; green = Agent (Person or Organisation).

So, the question is how/whether this applies for the SALDA/MOA cases I describe above.

For the “topic collections” case, the link is simply to a concept (a member of a “MOA Topics” “Concept Scheme”), and there isn’t a separate physical entity involved.

For the “place series” case, in theory we could introduce a set of concepts but I’m not sure there is any value in doing so – there is no external thesaurus/authority file involved, and I think it’s reasonable to simply make the direct link between archival resource and place.

The keyword matching case actually covers various sub-cases, and I need to think harder about them, but broadly I think we should try to avoid the complexity of the “intermediate” concept where it isn’t really necessary.


In short, while I need to do some more work on it, it’s been relatively straightforward to apply the model and the transformation processes developed in LOCAH to the MOA data.

What is perhaps more interesting is how we’ve “specialised” the fairly “general” LOCAH approach, based on Karen’s “local knowledge” of specific characteristics of the MOA data.

While it’s perhaps premature to draw general conclusions from this single case, I do wonder whether that the nature of the EAD format and the ways it is used may mean that this combination of the general and the local/specific turns out be a common pattern e.g. for a different dataset, a different set of “local”/specific characteristics might be identified and exploited in a similar fashion. Amongst other things, I should probably think about how this is reflected in the transformation process, e.g. whether it is possible to “modularise” the XSLT transform in such a way that it the “general” parts are separated from the “specific” ones, and it is easier to “plug in” versions of the latter as required.

URIs. A decision

Tuesday, May 10th, 2011

The project team at Sussex (Jane Harvell, Fiona Courage, Chris Keene and myself) met for an hour yesterday to decide about the URI stem for our data.

We took 20 minutes. Did we make a hasty decision? No. Did we make a considered, long term, looking to the future sort of decision? Yes. The combined expertise round the table was very useful; Jane is very library and looks to the digital future, Fiona is very involved with the Keep and our identity when we are there, Chris knows about servers and how that bit works. We considered the comments from Rob Styles and the advice from Pete Johnston at Eduserv and we decided on;

We wanted something that could work with other archive collections (if we decide to make them into linked data) so a Mass Observation or Massobs stem was too exclusive. We also wanted to avoid creating lots and lots of URIs for the same thing in the future so a generic stem seemed the way to go.