Lightning fast, asynchronous, streaming Turtle for JavaScript
The node-n3 library lets you handle Turtle and RDF in JavaScript easily.
It offers:
It has the following characteristics:
- extreme performance – by far the fastest parser in JavaScript
- asynchronous – triples arrive as soon as possible
- streaming – streams are parsed as data comes in, so you can easily parse files that don't fit into memory
At a later stage, this library will support Notation3 (N3),
a Turtle superset.
Installation
node-n3 comes as an npm package.
$ npm install n3
var n3 = require('n3');
Triple representation
For maximum performance and easy of use,
triples are represented as simple objects.
Since URIs are most common when dealing with RDF,
they are represented as simple strings.
@prefix c: <http://example.org/cartoons#>.
c:Tom a c:Cat.
is represented as
{
subject: 'http://example.org/cartoons#Tom',
predicate: 'http://www.w3.org/1999/02/22-rdf-syntax-ns#type',
object: 'http://example.org/cartoons#Cat'
}
Literals are represented as double quoted strings.
c:Tom c:name "Tom".
is represented as
{
subject: 'http://example.org/cartoons#Tom',
predicate: 'http://example.org/cartoons#name',
object: '"Tom"'
}
This allows you to create and compare literals fast and easily:
triple.object === 'http://example.org/cartoons#Cat'
triple.object === '"Tom"'
The Utility section details entity representation in more depth.
Parsing
From a Turtle string to triples
n3.Parser
parses strings into triples using a callback.
var parser = new require('n3').Parser();
parser.parse('@prefix c: <http://example.org/cartoons#>.\n' +
'c:Tom a c:Cat.\n' +
'c:Jerry a c:Mouse;\n' +
' c:smarterThan c:Tom.',
function (error, triple) {
if (triple)
console.log(triple.subject, triple.predicate, triple.object, '.');
else
console.log("# That's all, folks!")
});
From a Turtle stream to triples
n3.Parser
can parse streams as they grow, returning triples as soon as they're ready.
This behavior sets node-n3 apart from most other Turtle libraries.
var parser = new require('n3').Parser(),
turtleStream = fs.createReadStream('cartoons.ttl');
parser.parse(turtleStream, console.log);
In addition, n3.StreamParser
offers a Node Stream implementation,
so you can transform Turtle streams and pipe them to anywhere.
This solution is ideal if your consumer is slower,
as it avoids parser backpressure.
var streamParser = new require('n3').StreamParser(),
turtleStream = fs.createReadStream('cartoons.ttl');
turtleStream.pipe(streamParser);
streamParser.pipe(new SlowConsumer());
function SlowConsumer() {
var writer = new require('stream').Writable({ objectMode: true });
writer._write = function (triple, encoding, done) {
console.log(triple);
setTimeout(done, 1000);
};
return writer;
}
Storing
In this example below, we create a new store and add the triples :Pluto a :Dog.
and :Mickey a :Mouse
.
Then, we find a triple with :Mickey
as subject.
var store = new require('n3').Store();
store.add(':Pluto', 'a', ':Dog');
store.add(':Mickey', 'a', ':Mouse');
var mickey = store.find(':Mickey', null, null)[0];
console.log(mickey.subject, mickey.predicate, mickey.object, '.');
Writing
From triples to a Turtle stream
n3.Writer
writes triples to an output stream.
var writer = new require('n3').Writer(process.stdout);
writer.addTriple({
subject: 'http://example.org/cartoons#Tom',
predicate: 'http://www.w3.org/1999/02/22-rdf-syntax-ns#type',
object: 'http://example.org/cartoons#Cat'
});
writer.addTriple({
subject: 'http://example.org/cartoons#Tom',
predicate: 'http://example.org/cartoons#name',
object: '"Tom"'
});
writer.end();
From a triple stream to a Turtle stream
n3.StreamWriter
is a Turtle writer implementation as a Node Stream.
var n3 = require('n3'),
streamParser = new n3.StreamParser(),
inputStream = fs.createReadStream('cartoons.ttl'),
streamWriter = new n3.StreamWriter();
inputStream.pipe(streamParser);
streamParser.pipe(streamWriter);
streamWriter.pipe(process.stdout);
Utility
n3.Util
offers helpers for URI and literal representations.
As URIs are most common, they are represented as simple strings:
var N3Util = require('n3').Util;
N3Util.isUri('http://example.org/cartoons#Mickey');
Literals are represented as double quoted strings:
N3Util.isLiteral('"Mickey Mouse"');
N3Util.getLiteralValue('"Mickey Mouse"');
N3Util.isLiteral('"Mickey Mouse"@en');
N3Util.getLiteralLanguage('"Mickey Mouse"@en');
N3Util.isLiteral('"3"^^<http://www.w3.org/2001/XMLSchema#integer>');
N3Util.getLiteralType('"3"^^<http://www.w3.org/2001/XMLSchema#integer>');
N3Util.isLiteral('"http://example.org/"');
N3Util.getLiteralValue('"http://example.org/"');
Note the difference between 'http://example.org/'
(URI) and '"http://example.org/"'
(literal).
Also note that the double quoted literals are not raw Turtle syntax:
N3Util.isLiteral('"This word is "quoted"!"');
The above string represents the string This word is "quoted"!,
even though the correct Turtle syntax for that is "This word is \"quoted\"!"
node-n3 thus always parses literals, but adds quotes to differentiate from URIs:
new n3.Parser().parse('<a> <b> "This word is \\"quoted\\"!".', console.log);
For convenience, N3Util
can also be loaded globally:
require('n3').Util(global);
isUri('http://example.org/cartoons#Mickey');
isLiteral('"Mickey Mouse"');
If desired, the methods can even be added directly on all strings:
require('n3').Util(String, true);
'http://example.org/cartoons#Mickey'.isUri();
'"Mickey Mouse"'.isLiteral();
License, status and contributions
The node-n3 library is copyrighted by Ruben Verborgh
and released under the MIT License.
Current versions are considered beta, so the API might change from release to release.
As such, it is best to depend on a specific version of the package.
Contributions are welcome, and bug reports or pull requests are always helpful.
If you plan to implement larger features, it's best to contact me first.