A couple of weeks ago, I wrote an Introduction To RDF. In that article, we discussed expressing a RDF single triple (which defined the location of my blog) as a blob and line diagram. But what if we want to describe more than one aspect of a resource?… or if we want to model the relationships between many resources? It probably wouldn’t come as a surprise that to do that, you’d need to create multiple triples. As I mentioned in that previous post, blob and line diagrams only work well for small numbers of triples, and they’re only really good for humans.

To communicate RDF between computer systems, we need something different. In this article, we’ll see how to serialise a graph (i.e. a collection, or set) of RDF triples in different ways, and explore the advantages and disadvantages of each.

In order to avoid me having to make up a contrived example, I’m going to use some data from the OpenDataCommunities site, which contains a bunch of open data about English Local Authorities. The URI http://opendatacommunities.org/id/metropolitan-district-council/manchester identifies the Manchester Metropolitan District Council. If you click on that link, you’ll get an HTML representation of the data that the site holds about that authority.

But the site also offers the data in other formats via links at the bottom of the page. Let’s discuss each of those formats in turn.

RDF/XML

RDF is most commonly expressed in an XML format: RDF/XML.

A Single Resource as RDF/XML

The RDF/XML for what we know about the Manchester authority looks like this:

<?xml version="1.0" encoding="UTF-8"?>
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:ns0="http://opendatacommunities.org/def/local-government/" xmlns:ns1="http://data.ordnancesurvey.co.uk/ontology/admingeo/" xmlns:ns2="http://statistics.data.gov.uk/def/administrative-geography/" xmlns:ns3="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:ns4="http://www.w3.org/2000/01/rdf-schema#" xmlns:ns5="http://www.w3.org/2002/07/owl#" xmlns:ns6="http://xmlns.com/foaf/0.1/">
  <ns0:MetropolitanDistrictCouncil rdf:about="http://opendatacommunities.org/id/metropolitan-district-council/manchester">
    <ns1:gssCode>E08000003</ns1:gssCode>
    <ns1:hasCensusCode>00BN</ns1:hasCensusCode>
    <ns0:billingAuthorityCode>E4203</ns0:billingAuthorityCode>
    <ns0:governs rdf:resource="http://data.ordnancesurvey.co.uk/id/7000000000018821"/>
    <ns0:openlyLocalUrl rdf:resource="http://openlylocal.com/councils/157-Manchester-City-Council"/>
    <ns2:region rdf:resource="http://statistics.data.gov.uk/id/government-office-region/B"/>
    <ns3:type rdf:resource="http://opendatacommunities.org/def/local-government/CivilAdministrativeAuthority"/>
    <ns3:type rdf:resource="http://opendatacommunities.org/def/local-government/LocalAuthority"/>
    <ns4:label>Manchester</ns4:label>
    <ns5:sameAs rdf:resource="http://statistics.data.gov.uk/id/local-authority/00BN"/>
    <ns6:page rdf:resource="http://www.manchester.gov.uk/"/>
  </ns0:MetropolitanDistrictCouncil>
</rdf:RDF>

Multiple Resources as RDF/XML

A couple of local authorities serialised as RDF/XML look like this:

<?xml version="1.0"?>
<rdf:RDF
    xmlns:j.0="http://data.ordnancesurvey.co.uk/ontology/admingeo/"
    xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
    xmlns:j.1="http://xmlns.com/foaf/0.1/"
    xmlns:j.2="http://opendatacommunities.org/def/local-government/"
    xmlns:owl="http://www.w3.org/2002/07/owl#"
    xmlns:j.3="http://statistics.data.gov.uk/def/administrative-geography/"
    xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#" >
  <rdf:Description rdf:about="http://opendatacommunities.org/id/district-council/babergh">
    <j.2:governs rdf:resource="http://data.ordnancesurvey.co.uk/id/7000000000015692"/>
    <j.0:hasCensusCode>42UB</j.0:hasCensusCode>
    <j.2:billingAuthorityCode>E3531</j.2:billingAuthorityCode>
    <rdfs:label>Babergh</rdfs:label>
    <j.1:page rdf:resource="http://www.babergh.gov.uk"/>
    <rdf:type rdf:resource="http://opendatacommunities.org/def/local-government/LocalAuthority"/>
    <rdf:type rdf:resource="http://opendatacommunities.org/def/local-government/DistrictCouncil"/>
    <j.0:gssCode>E07000200</j.0:gssCode>
    <owl:sameAs rdf:resource="http://statistics.data.gov.uk/id/local-authority/42UB"/>
    <j.3:region rdf:resource="http://statistics.data.gov.uk/id/government-office-region/G"/>
    <rdf:type rdf:resource="http://opendatacommunities.org/def/local-government/CivilAdministrativeAuthority"/>
  </rdf:Description>
  <rdf:Description rdf:about="http://opendatacommunities.org/id/london-borough-council/barking-and-dagenham">
    <owl:sameAs rdf:resource="http://statistics.data.gov.uk/id/local-authority/00AB"/>
    <j.0:gssCode>E09000002</j.0:gssCode>
    <rdf:type rdf:resource="http://opendatacommunities.org/def/local-government/CivilAdministrativeAuthority"/>
    <j.2:openlyLocalUrl rdf:resource="http://openlylocal.com/councils/19-London-Borough-of-Barking-Dagenham"/>
    <rdf:type rdf:resource="http://opendatacommunities.org/def/local-government/LondonBoroughCouncil"/>
    <j.2:governs rdf:resource="http://data.ordnancesurvey.co.uk/id/7000000000010949"/>
    <rdf:type rdf:resource="http://opendatacommunities.org/def/local-government/LocalAuthority"/>
    <j.0:hasCensusCode>00AB</j.0:hasCensusCode>
    <j.3:region rdf:resource="http://statistics.data.gov.uk/id/government-office-region/H"/>
    <j.1:page rdf:resource="http://www.lbbd.gov.uk/"/>
    <j.2:billingAuthorityCode>E5030</j.2:billingAuthorityCode>
    <rdfs:label>Barking and Dagenham</rdfs:label>
  </rdf:Description>
</rdf:RDF>

Mime Type

RDF/XML is typically requested and sent over the Web using a MIME type of application/rdf+xml.

RDF/XML Summary

In RDF/XML, the triples for each resource, are contained within <rdf:Description> nodes, with a sub-node for each property and its value (full spec here).

This format has the advantage that most programming languages have support for XML, and you can make use of XML namespaces to avoid having to use full URIs everywhere, which keeps the size down. On the other hand, I don’t find it that easy to read manually.

Turtle

Turtle (Terse RDF Triple Language) is an RDF-specific subset of Tim Berners-Lee’s Notation3 language.

A Single Resource as Turtle

The RDF triples about that single Manchester authority could be represented in Turtle like this:

@prefix gov: <http://opendatacommunities.org/def/local-government/> .
@prefix admingeo: <http://data.ordnancesurvey.co.uk/ontology/admingeo/> .
@prefix statsgeo: <http://statistics.data.gov.uk/def/administrative-geography/> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix owl: <http://www.w3.org/2002/07/owl#> .
@prefix foaf: <http://xmlns.com/foaf/0.1/> .

<http://opendatacommunities.org/id/metropolitan-district-council/manchester>
   a gov:MetropolitanDistrictCouncil, gov:LocalAuthority, gov:CivilAdministrativeAuthority;
   rdfs:label "Manchester";
   admingeo:gssCode "E08000003";
   admingeo:hasCensusCode "00BN";
   gov:billingAuthorityCode "E4203";
   gov:governs <http://data.ordnancesurvey.co.uk/id/7000000000018821>;
   gov:openlyLocalUrl <http://openlylocal.com/councils/157-Manchester-City-Council>;
   statsgeo:region <http://statistics.data.gov.uk/id/government-office-region/B>;
   owl:sameAs <http://statistics.data.gov.uk/id/local-authority/00BN>;
   foaf:page <http://www.manchester.gov.uk/> .

Multiple Resources as Turtle

Multiple local authorities could be serialised in Turtle like this:

@prefix gov: <http://opendatacommunities.org/def/local-government/> .
@prefix admingeo: <http://data.ordnancesurvey.co.uk/ontology/admingeo/> .
@prefix statsgeo: <http://statistics.data.gov.uk/def/administrative-geography/> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix owl: <http://www.w3.org/2002/07/owl#> .
@prefix foaf: <http://xmlns.com/foaf/0.1/> .

<http://opendatacommunities.org/id/district-council/babergh>
    a gov:LocalAuthority, gov:DistrictCouncil, gov:CivilAdministrativeAuthority ;
    rdfs:label "Babergh" ;
    admingeo:gssCode "E07000200" ;
    admingeo:hasCensusCode "42UB" ;
    admingeo:billingAuthorityCode "E3531" ;
    gov:governs <http://data.ordnancesurvey.co.uk/id/7000000000015692> ;
    statsgeo:region  <http://statistics.data.gov.uk/id/government-office-region/G> ;
    owl:sameAs <http://statistics.data.gov.uk/id/local-authority/42UB> ;
    foaf:page <http://www.babergh.gov.uk> .

<http://opendatacommunities.org/id/london-borough-council/barking-and-dagenham>
    a gov:LocalAuthority, gov:LondonBoroughCouncil, gov:CivilAdministrativeAuthority ;
    rdfs:label "Barking and Dagenham" ;
    admingeo:gssCode "E09000002" ;
    admingeo:hasCensusCode "00AB" ;
    gov:billingAuthorityCode "E5030" ;
    gov:governs <http://data.ordnancesurvey.co.uk/id/7000000000010949> ;
    gov:openlyLocalUrl <http://openlylocal.com/councils/19-London-Borough-of-Barking-Dagenham> ;
    statsgeo:region <http://statistics.data.gov.uk/id/government-office-region/H> ;
    owl:sameAs <http://statistics.data.gov.uk/id/local-authority/00AB> ;
    foaf:page <http://www.lbbd.gov.uk/> .

Mime Type

Turtle is typically requested and sent over the Web using a MIME type of text/turtle.

Turtle Summary

The URI for the each resource is followed by the predicates and objects of the triples about it (essentially, as key-value pairs). Each pair is separated by a semi-colon, and the information about a resource is closed off by a dot. Note that the whitespace is not important here, but for readability, the predicates and objects are often indented and appear on separate lines.

Turtle is my favourite RDF serialisation format: It’s fairly easy to read for humans due to the lack of punctuation noise, it groups together the triples about each resource, and it allows you to define common @prefixes. Its terseness also helps keep the amount of bandwidth required to communicate RDF down to a minimum, and it’s well supported by RDF toolkits and libraries.

Note that the standard encoding of Turtle is UTF-8 (though escaped Unicode is allowed in Turtle as well). Turtle literals can contain line breaks, using the """long literal""" approach. For more information, see the Turtle W3C submission.

N-Triples

N-Triples is a simplified version of Turtle.

A Single Resource as N-Triples

Here’s the RDF for the Manchester authority again, this time as N-triples.

<http://opendatacommunities.org/id/metropolitan-district-council/manchester> <http://www.w3.org/2000/01/rdf-schema#label> "Manchester" .
<http://opendatacommunities.org/id/metropolitan-district-council/manchester> <http://opendatacommunities.org/def/local-government/openlyLocalUrl> <http://openlylocal.com/councils/157-Manchester-City-Council> .
<http://opendatacommunities.org/id/metropolitan-district-council/manchester> <http://xmlns.com/foaf/0.1/page> <http://www.manchester.gov.uk/> .
<http://opendatacommunities.org/id/metropolitan-district-council/manchester> <http://www.w3.org/2002/07/owl#sameAs> <http://statistics.data.gov.uk/id/local-authority/00BN> .
<http://opendatacommunities.org/id/metropolitan-district-council/manchester> <http://data.ordnancesurvey.co.uk/ontology/admingeo/hasCensusCode> "00BN" .
<http://opendatacommunities.org/id/metropolitan-district-council/manchester> <http://opendatacommunities.org/def/local-government/billingAuthorityCode> "E4203" .
<http://opendatacommunities.org/id/metropolitan-district-council/manchester> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://opendatacommunities.org/def/local-government/MetropolitanDistrictCouncil> .
<http://opendatacommunities.org/id/metropolitan-district-council/manchester> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://opendatacommunities.org/def/local-government/LocalAuthority> .
<http://opendatacommunities.org/id/metropolitan-district-council/manchester> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://opendatacommunities.org/def/local-government/CivilAdministrativeAuthority> .
<http://opendatacommunities.org/id/metropolitan-district-council/manchester> <http://opendatacommunities.org/def/local-government/governs> <http://data.ordnancesurvey.co.uk/id/7000000000018821> .
<http://opendatacommunities.org/id/metropolitan-district-council/manchester> <http://statistics.data.gov.uk/def/administrative-geography/region> <http://statistics.data.gov.uk/id/government-office-region/B> .
<http://opendatacommunities.org/id/metropolitan-district-council/manchester> <http://data.ordnancesurvey.co.uk/ontology/admingeo/gssCode> "E08000003" .

Multiple Resources as N-Triples

<http://opendatacommunities.org/id/district-council/allerdale> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://opendatacommunities.org/def/local-government/CivilAdministrativeAuthority> .
<http://opendatacommunities.org/id/district-council/allerdale> <http://opendatacommunities.org/def/local-government/billingAuthorityCode> "E0931" .
<http://opendatacommunities.org/id/district-council/allerdale> <http://www.w3.org/2002/07/owl#sameAs> <http://statistics.data.gov.uk/id/local-authority/16UB> .
<http://opendatacommunities.org/id/district-council/allerdale> <http://opendatacommunities.org/def/local-government/openlyLocalUrl> <http://openlylocal.com/councils/38-Allerdale-Borough-Council> .
<http://opendatacommunities.org/id/district-council/allerdale> <http://opendatacommunities.org/def/local-government/governs> <http://data.ordnancesurvey.co.uk/id/7000000000013065> .
<http://opendatacommunities.org/id/district-council/allerdale> <http://www.w3.org/2000/01/rdf-schema#label> "Allerdale" .
<http://opendatacommunities.org/id/district-council/allerdale> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://opendatacommunities.org/def/local-government/DistrictCouncil> .
<http://opendatacommunities.org/id/district-council/allerdale> <http://xmlns.com/foaf/0.1/page> <http://www.allerdale.gov.uk> .
<http://opendatacommunities.org/id/district-council/allerdale> <http://statistics.data.gov.uk/def/administrative-geography/region> <http://statistics.data.gov.uk/id/government-office-region/B> .
<http://opendatacommunities.org/id/district-council/allerdale> <http://data.ordnancesurvey.co.uk/ontology/admingeo/gssCode> "E07000026" .
<http://opendatacommunities.org/id/district-council/allerdale> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://opendatacommunities.org/def/local-government/LocalAuthority> .
<http://opendatacommunities.org/id/district-council/allerdale> <http://data.ordnancesurvey.co.uk/ontology/admingeo/hasCensusCode> "16UB" .
<http://opendatacommunities.org/id/district-council/barrow-in-furness> <http://opendatacommunities.org/def/local-government/governs> <http://data.ordnancesurvey.co.uk/id/7000000000012941> .
<http://opendatacommunities.org/id/district-council/barrow-in-furness> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://opendatacommunities.org/def/local-government/CivilAdministrativeAuthority> .
<http://opendatacommunities.org/id/district-council/barrow-in-furness> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://opendatacommunities.org/def/local-government/LocalAuthority> .
<http://opendatacommunities.org/id/district-council/barrow-in-furness> <http://opendatacommunities.org/def/local-government/billingAuthorityCode> "E0932" .
<http://opendatacommunities.org/id/district-council/barrow-in-furness> <http://www.w3.org/2002/07/owl#sameAs> <http://statistics.data.gov.uk/id/local-authority/16UC> .
<http://opendatacommunities.org/id/district-council/barrow-in-furness> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://opendatacommunities.org/def/local-government/DistrictCouncil> .
<http://opendatacommunities.org/id/district-council/barrow-in-furness> <http://xmlns.com/foaf/0.1/page> <http://www.barrowbc.gov.uk/> .
<http://opendatacommunities.org/id/district-council/barrow-in-furness> <http://data.ordnancesurvey.co.uk/ontology/admingeo/gssCode> "E07000027" .
<http://opendatacommunities.org/id/district-council/barrow-in-furness> <http://data.ordnancesurvey.co.uk/ontology/admingeo/hasCensusCode> "16UC" .
<http://opendatacommunities.org/id/district-council/barrow-in-furness> <http://www.w3.org/2000/01/rdf-schema#label> "Barrow-in-Furness" .
<http://opendatacommunities.org/id/district-council/barrow-in-furness> <http://statistics.data.gov.uk/def/administrative-geography/region> <http://statistics.data.gov.uk/id/government-office-region/B> .

Mime Type

N-triples are typically requested and sent over the Web using a MIME type of text/plain or application/n-triples.

N-Triples summary

With N-triples, each triple appears on its own line, separated by a dot.

N-triples’ simplicity makes it easy for software to parse and generate, but it lacks some of the features of RDF/XML and Turtle (such as support for nested resources). Due to the repetition of the resource URIs, it’s not as compact as Turtle, and the triples for each resource aren’t necessarily grouped together which makes it harder to read by eye.

It’s also worth mentioning here that as N-triples is a text/plain literals are only allowed to contain US ASCII characters: non-ASCII Unicode characters need to be escaped (in contrast to Turtle whose standard encoding is UTF-8). Also, in N-triples, line-breaks always need to be escaped.

This section of the W3C Turtle submission gives a useful comparison between Turtle and N-Triples. You can also find more details about N-Triples here.

JSON

RDF can also be expressed in JavaScript Object Notation (JSON).

A Single Resource as JSON

{"http://opendatacommunities.org/id/metropolitan-district-council/manchester":{"http://www.w3.org/2000/01/rdf-schema#label":[{"type":"literal","value":"Manchester"}],"http://opendatacommunities.org/def/local-government/openlyLocalUrl":[{"type":"uri","value":"http://openlylocal.com/councils/157-Manchester-City-Council"}],"http://xmlns.com/foaf/0.1/page":[{"type":"uri","value":"http://www.manchester.gov.uk/"}],"http://www.w3.org/2002/07/owl#sameAs":[{"type":"uri","value":"http://statistics.data.gov.uk/id/local-authority/00BN"}],"http://data.ordnancesurvey.co.uk/ontology/admingeo/hasCensusCode":[{"type":"literal","value":"00BN"}],"http://opendatacommunities.org/def/local-government/billingAuthorityCode":[{"type":"literal","value":"E4203"}],"http://www.w3.org/1999/02/22-rdf-syntax-ns#type":[{"type":"uri","value":"http://opendatacommunities.org/def/local-government/MetropolitanDistrictCouncil"},{"type":"uri","value":"http://opendatacommunities.org/def/local-government/LocalAuthority"},{"type":"uri","value":"http://opendatacommunities.org/def/local-government/CivilAdministrativeAuthority"}],"http://opendatacommunities.org/def/local-government/governs":[{"type":"uri","value":"http://data.ordnancesurvey.co.uk/id/7000000000018821"}],"http://statistics.data.gov.uk/def/administrative-geography/region":[{"type":"uri","value":"http://statistics.data.gov.uk/id/government-office-region/B"}],"http://data.ordnancesurvey.co.uk/ontology/admingeo/gssCode":[{"type":"literal","value":"E08000003"}]}}

Multiple Resources as JSON

{"http://opendatacommunities.org/id/district-council/allerdale":{"http://www.w3.org/1999/02/22-rdf-syntax-ns#type":[{"type":"uri","value":"http://opendatacommunities.org/def/local-government/CivilAdministrativeAuthority"},{"type":"uri","value":"http://opendatacommunities.org/def/local-government/DistrictCouncil"},{"type":"uri","value":"http://opendatacommunities.org/def/local-government/LocalAuthority"}],"http://opendatacommunities.org/def/local-government/billingAuthorityCode":[{"type":"literal","value":"E0931"}],"http://www.w3.org/2002/07/owl#sameAs":[{"type":"uri","value":"http://statistics.data.gov.uk/id/local-authority/16UB"}],"http://opendatacommunities.org/def/local-government/openlyLocalUrl":[{"type":"uri","value":"http://openlylocal.com/councils/38-Allerdale-Borough-Council"}],"http://opendatacommunities.org/def/local-government/governs":[{"type":"uri","value":"http://data.ordnancesurvey.co.uk/id/7000000000013065"}],"http://www.w3.org/2000/01/rdf-schema#label":[{"type":"literal","value":"Allerdale"}],"http://xmlns.com/foaf/0.1/page":[{"type":"uri","value":"http://www.allerdale.gov.uk"}],"http://statistics.data.gov.uk/def/administrative-geography/region":[{"type":"uri","value":"http://statistics.data.gov.uk/id/government-office-region/B"}],"http://data.ordnancesurvey.co.uk/ontology/admingeo/gssCode":[{"type":"literal","value":"E07000026"}],"http://data.ordnancesurvey.co.uk/ontology/admingeo/hasCensusCode":[{"type":"literal","value":"16UB"}]},"http://opendatacommunities.org/id/district-council/barrow-in-furness":{"http://opendatacommunities.org/def/local-government/governs":[{"type":"uri","value":"http://data.ordnancesurvey.co.uk/id/7000000000012941"}],"http://www.w3.org/1999/02/22-rdf-syntax-ns#type":[{"type":"uri","value":"http://opendatacommunities.org/def/local-government/CivilAdministrativeAuthority"},{"type":"uri","value":"http://opendatacommunities.org/def/local-government/LocalAuthority"},{"type":"uri","value":"http://opendatacommunities.org/def/local-government/DistrictCouncil"}],"http://opendatacommunities.org/def/local-government/billingAuthorityCode":[{"type":"literal","value":"E0932"}],"http://www.w3.org/2002/07/owl#sameAs":[{"type":"uri","value":"http://statistics.data.gov.uk/id/local-authority/16UC"}],"http://xmlns.com/foaf/0.1/page":[{"type":"uri","value":"http://www.barrowbc.gov.uk/"}],"http://data.ordnancesurvey.co.uk/ontology/admingeo/gssCode":[{"type":"literal","value":"E07000027"}],"http://data.ordnancesurvey.co.uk/ontology/admingeo/hasCensusCode":[{"type":"literal","value":"16UC"}],"http://www.w3.org/2000/01/rdf-schema#label":[{"type":"literal","value":"Barrow-in-Furness"}],"http://statistics.data.gov.uk/def/administrative-geography/region":[{"type":"uri","value":"http://statistics.data.gov.uk/id/government-office-region/B"}]}}

Mime Type

JSON is typically requested and sent over the Web using a MIME type of application/json.

JSON Summary

This format serialises the triples by defining JavaScript objects, the identifier for each being the URI for the resource. Sub-objects are created for each predicate, the values being an array of the triples for that predicate. For each object of the triple, there is a JavaScript object with properties for its type (i.e. URI or literal), and actual value.

It’s not an official standard (the example above is an output from the rdf.rb ruby library, which is based on Talis’s RDF JSON spec), but many Linked Data sites are now supporting JSON as a serialisation format. It’s becoming popular due to the ease with which this kind of data can be consumed in JavaScript web applications. It’s not as easy to read by eye as Turtle (to me, at least), but it’s still not too bad in that respect. The limited punctuation also helps to keep the size down.

Conclusion

In this article, we’ve covered the most common serialisation formats for RDF triples. Hopefully it has helped you to understand the benefits and pitfalls of each, so that you can make an informed decision about which to choose for publishing or consuming your Linked Data.

Keep up to date with our news by signing up to our newsletter.
Thanks for reading all the way to the end!
We'd love it if you shared this article.