4.1.1 • Public • Published

RDF for ECMAScript

This package is a set of utilities aimed at making it simple to represent RDF data. It is targeted at Node.js, but should work cross-environment.

RDF can be considered a superset of typical links found on the Web: It allows a collection of directional relationships from some subject, with a relationship predicate, to some object.

On the Web, normally all three are documents. In RDF, the object may also be a literal string containing data; and the subject or object may be an existential quantifier called a blank node.

The NamedNode, BlankNode, and Literal objects represent the fundamental types of data that can be found in an RDF Statement. Statements are represented as Triple.

RDF doesn't define any representation of a blank nodes, except for the fact it is possible to compare two blank nodes to see if they are the same. In RDF Interfaces, a bnode is uniquely represented as an instance of BlankNode. This interface optionally allows a label, this is primarily for debugging, and two instances of BlankNodes with the same label may still represent different blank nodes.

The library also exposes a function to decorate the builtin ECMAScript protoypes with methods.


Represent RDF nodes

NamedNode, BlankNode, and Literal instances represent nodes in an RDF graph.

const rdf = require('rdf');
const { NamedNode, BlankNode, Literal } = rdf;

const namednode = new NamedNode('http://example.com/');
const blanknode = new BlankNode();
const literal = new Literal('plain string');
'"plain string"'

A factory-style interface is also available:

const rdfjs = rdf.factory;
BlankNode { nominalValue: 'b2' }

As well as the RDF Interfaces environment:

const rdfenv = rdf.environment;
rdfenv.createLiteral("true", null, rdf.xsdns("boolean")).toTurtle()

Represent RDF statements

A Triple instance represents an edge in an RDF graph (also known as a Statement).

const statement1 = rdfjs.triple(blanknode, namednode, literal);
'_:b1 <http://example.com/> "plain string" .'

Represent RDF graphs

A Graph instance stores and queries for Triples:

const graph = new rdf.Graph();
graph.add(new rdf.Triple(
	new BlankNode(),
	new Literal('Book', '@en'))
graph.add(new rdf.Triple(
	new BlankNode(),
	new Literal('10.0', rdf.xsdns('decimal')))
graph.add(new rdf.Triple(
	new BlankNode(),
	new Literal('10.1', rdf.xsdns('decimal')))
	.match(null, rdf.rdfns('value'), null)
	.forEach(function(triple){ console.log(triple.toString()); });
_:b4 <http://www.w3.org/1999/02/22-rdf-syntax-ns#value> "10.0"^^<http://www.w3.org/2001/XMLSchema#decimal> .
_:b5 <http://www.w3.org/1999/02/22-rdf-syntax-ns#value> "10.1"^^<http://www.w3.org/2001/XMLSchema#decimal> .

Simplify RDF namespaces

Use the ns function to create a URI factory.

const foaf = rdf.ns('http://xmlns.com/foaf/0.1/');

Use the builtin rdfns, rdfsns, and xsdns functions too:


Compare nodes, triples, and graphs for equality

Use the NamedNode#equals, BlankNode#equals, Literal#equals, Triple#equals, and Graph#isomorphic methods to compare equality.

Literals verify codepoint, datatype, and language tag equality. Triples verify equality of each three nodes.

Graphs test for isomorphism, that there's a mapping that can map the blank nodes in one graph to the blank nodes in the other one-to-one. If so isomorphic, it returns the mapping.

const graph2 = new rdf.Graph();
const bn2 = rdf.factory.blankNode();

	rdfjs.literal('10.0', rdf.xsdns('decimal'))


Compose RDF graphs as native Objects

Use the rdf.parse function to cast a native object into a graph:

const person = rdf.ns('http://example.com/');
const partyDocument = rdf.parse({
	"@context": {
		"@vocab": "http://xmlns.com/foaf/0.1/",
		"foaf": "http://xmlns.com/foaf/0.1/",
		"person": "http://example.com/",
	"@id": person('a'),
	givenname: rdfjs.literal("Alice"),
	age: 26,
	knows: [
			"@id": person('b'),
			givenname: rdfjs.literal("Bob"),
			age: 36,
			knows: person('a'),
			"@id": person('c'),
			givenname: rdfjs.literal("Carol"),
			age: 46,
			knows: person('a'),
			"@id": person('d'),
			givenname: rdfjs.literal("Dan"),
			age: 56,
			knows: [person('a'), person('b')],
	foaf:givenname "Alice";
	foaf:age 26;
	foaf:knows [
		foaf:givenname "Bob";
		foaf:age 36;
		foaf:knows person:a
		], [
		foaf:givenname "Carol";
		foaf:age 46;
		foaf:knows person:a
		], [
		foaf:givenname "Dan";
		foaf:age 56;
		foaf:knows person:a, person:b

Use the graphify method to produce an rdf.Graph from the data:

const partyGraph = partyDocument.graphify();

	.sort(function(a,b){ return a.compare(b); })
	.forEach(function(triple){ console.log(triple.toString()); });
<http://example.com/a> <http://xmlns.com/foaf/0.1/age> "26"^^<http://www.w3.org/2001/XMLSchema#integer> .
<http://example.com/a> <http://xmlns.com/foaf/0.1/givenname> "Alice" .
<http://example.com/a> <http://xmlns.com/foaf/0.1/knows> <http://example.com/b> .
<http://example.com/a> <http://xmlns.com/foaf/0.1/knows> <http://example.com/c> .
<http://example.com/a> <http://xmlns.com/foaf/0.1/knows> <http://example.com/d> .
<http://example.com/b> <http://xmlns.com/foaf/0.1/age> "36"^^<http://www.w3.org/2001/XMLSchema#integer> .
<http://example.com/b> <http://xmlns.com/foaf/0.1/givenname> "Bob" .
<http://example.com/b> <http://xmlns.com/foaf/0.1/knows> <http://example.com/a> .
<http://example.com/c> <http://xmlns.com/foaf/0.1/age> "46"^^<http://www.w3.org/2001/XMLSchema#integer> .
<http://example.com/c> <http://xmlns.com/foaf/0.1/givenname> "Carol" .
<http://example.com/c> <http://xmlns.com/foaf/0.1/knows> <http://example.com/a> .
<http://example.com/d> <http://xmlns.com/foaf/0.1/age> "56"^^<http://www.w3.org/2001/XMLSchema#integer> .
<http://example.com/d> <http://xmlns.com/foaf/0.1/givenname> "Dan" .
<http://example.com/d> <http://xmlns.com/foaf/0.1/knows> <http://example.com/a> .
<http://example.com/d> <http://xmlns.com/foaf/0.1/knows> <http://example.com/b> .

Query information from RDF sources

Use the ResultSet interface to quickly drill into the specific data you want:

// Get the name of Alice
// Get all the names of everyone who Alice knows
	.join(', ')
'Bob, Carol, Dan'

Read RDF data sources as native data types

Use Literal#valueOf to convert from lexical data space to native value space:

rdfjs.literal('2018-06-04T23:11:25Z', rdf.xsdns('date')).valueOf()
rdfjs.literal('24.4400', rdf.xsdns('decimal')).valueOf()
rdfjs.literal('0', rdf.xsdns('boolean')).valueOf()

Read the ages of everyone that Alice knows as a native number, and sum them:

// sum the ages of everyone that Alice knows
	.reduce(function(a, b){ return a.valueOf() + b; }, 0);

Manage documents with RDF data

Use the RDFEnvironment, Profile, TermMap, and ProfileMap interfaces to work with RDF documents that think in terms of CURIEs and Terms.

Here's an example to take an RDF graph, and output a Turtle document with the prefixes applied:

const profile = rdf.environment.createProfile();
profile.setPrefix('ff', 'http://xmlns.com/foaf/0.1/');
const turtle = partyGraph
	.sort(function(a,b){ return a.compare(b); })
		return stmt.toTurtle(profile);
:a ff:age 26 .
:a ff:givenname "Alice" .
:a ff:knows :b .
:a ff:knows :c .
:a ff:knows :d .
:b ff:age 36 .
:b ff:givenname "Bob" .
:b ff:knows :a .
:c ff:age 46 .
:c ff:givenname "Carol" .
:c ff:knows :a .
:d ff:age 56 .
:d ff:givenname "Dan" .
:d ff:knows :a .
:d ff:knows :b .

Treat native data types as RDF data

If you think creating RDF Term is too verbose, enable builtins mode with setBuiltins(). This amends the prototype of primitives:

  • Strings are treated as a NamedNode
  • String#l(langtag) produces a language Literal
  • String#tl(datatype) produces a typed Literal
  • Date, Boolean, Number are treated as a Literal

    (3 * 4).toNT(),
    new Date('2112-06-06').toNT(),
    "The Hobbit".l('en-GB').toNT(),
[ '<http://example.com/>',
  '"The Hobbit"@en-GB',
  '"4.0"^^<http://www.w3.org/2001/XMLSchema#decimal>' ]

Change your mind? Use unsetBuiltins to remove them:


Native support for RDF 1.1 semantics

The domains of the functions ensure consistency with all the other applications found in the RDF universe.

Literal treats xsd:string as no datatype, and treats any language literal as rdf:langString. The RDF1.1 datatype is available through the Literal#datatype property. The RDF1.0 datatype, which null for plain literals and language strings, is available through Literal#type.

const literal = new Literal('Foo');
const langLiteral = new Literal('Foo', '@en');
const typedLiteral = new Literal('Foo', rdf.xsdns('string'));

The data model is enforced in the domain of each of the functions; Triple doesn't allow bnodes as predicates, for example:

try {
    rdfjs.triple(rdfjs.blankNode(), rdfjs.blankNode(), rdfjs.blankNode());
Error: predicate must be a NamedNode

Parse Turtle data

Use the TurtleParser.parse(document, base) function to parse Turtle data into a Graph object:

const parse = rdf.TurtleParser.parse('<> a <Page> .', 'http://example.com/');
'<http://example.com/> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://example.com/Page> .'

Public Domain unlicensed

Use this library in whatever application you want! Give credit when you do so, or don't (but preferably the former). Use it to take over the world, or don't (but preferably the latter).


This implements:

See also:

Implementation largely adapted from webr3's js3, rdfa-api, and rdf-api implementations:

This is free and unencumbered software released into the public domain. For information, see http://unlicense.org/.



rdf.Triple, rdf.RDFNode, rdf.NamedNode, rdf.BlankNode, rdf.Literal are implemented as defined under RDF Interfaces: Basic Node Types.

For parsing the IRI and converting to a URI that can be used in an HTTP request, see the IRI package.


Represents an edge in an RDF Graph, also known as a Statement or a Triple.

Create an instance of a triple with rdf.environment.createTriple(subject, predicate, object).

Use the Triple#subject, Triple#predicate, and Triple#object properties to access the respective RDF nodes in the Triple.


Returns the triple encoded as N-Triples. Same as Triple#toNT().


Returns the triple encoded as N-Triples.


Returns the triple encoded as a statement in Turtle, optionally with the given prefix map applied.


Also exposed as Term, this is the abstract superclass of things that can be found in an RDF Triple.


Returns true if the given node other would be considered the same node as itself in an RDF graph.

Literals and NamedNodes always compare by their contents. BlankNodes sometimes compare by their label, but sometimes may only be equal if they're the same instance.

If you're managing a single RDF graph, you should keep a mapping of labels to BlankNode instances, and use the instances from this mapping, instead of creating a new BlankNode and setting the label.


Represents an IRI node in an RDF graph. Instances are uniquely identified by their contents, so two different contents will still be considered equal if the inner IRIs are the same.

Create an instance of a triple with rdf.environment.createTriple(subject, predicate, object).


Returns true if the given NamedNode other is the same IRI, otherwise false. See RDFNode#equals for details


Returns the inner IRI as a string.


Serializes the node as an IRI for N-Triples, inside angle brackets.


Serializes the node as an IRI for N-Triples inside angle brackets, or the shrunken CURIE form if provided in the optional profile.


Represents a blank node in an RDF graph. BlankNode instances are typically identified by their instance, so two instances may be considered different even if they have the same label.

Create an instance of a triple with rdf.environment.createBlankNode().


Returns true if the given NamedNode other is the same IRI, otherwise false. See RDFNode#equals for details


Serializes the node as a Turtle-style BlankNode. See toTurtle for information.


Serializes the node as a Turtle-style BlankNode. See toTurtle for information.


Serializes the BlankNode as a Turtle-style blank node, e.g.:

  • _:bn0
  • _:label


Represents a content literal in an RDF graph. Literals may have edges pointing only towards them (i.e. they're only found in the object position of a triple). Literals are Unicode strings with a datatype IRI, and optional associated language tag.

  • Literal#value - the string contents of the literal (note that ECMAScript/JavaScript uses UTF-16 to encode Unicode strings)
  • Literal#datatype - NamedNode that identifies the datatype of the literal.
  • Literal#type - getter that returns null if the datatype is an xsd:string, or a language literal, as seen in RDF1.0 semantics.
  • Literal#language - stores the language tag, if any, or null otherwise.


Returns a native representation of the literal, based on its datatype.

  • The numeric datatypes will produce a number: xsd:float, xsd:integer, xsd:long, xsd:double, xsd:decimal, xsd:nonPositiveInteger, xsd:nonNegativeInteger, xsd:negativeInteger, xsd:int, xsd:unsignedLong, xsd:positiveInteger, xsd:short, xsd:unsignedInt, xsd:byte, xsd:unsignedShort, xsd:unsignedByte
  • The datetime datatypes will produce a Date object: xsd:date, xsd:time, xsd:dateTime
  • The boolean datatype will produce a boolean: xsd:boolean
  • The string datatypes will produce a string: xsd:string rdf:langString


Returns true if the given Literal other has the same contents, datatype, and language tag. See RDFNode#equals for details.


Returns the literal contents as a string, discarding the other type/tags.


Serializes the node as a string with datatype for N-Triples, inside double-quotes followed by language tag or datatype IRI (if not xsd:string).


Serializes the node as a string. For datatypes of xsd:integer, xsd:decimal, xsd:double, xsd:boolean, and xsd:string, the literal is printed without the datatype IRI.

If the datatype IRI can be shrunk with the given profile, it is printed as a CURIE, otherwise it prints the full brackted IRI.


Represents a set of RDF Triple instances. Since a graph in RDF is a set of edges, nodes are only known to exist in the graph if there is an edge (a Triple) containing them.

This implements RDF Interfaces: Graph with three indexes for fast querying.

Instances of Graph are uniquely identified by their instance (however, Graph#equals tests isomorphism). Graphs are mutable. Methods with a return value are pure, non-pure (mutating) methods always return undefined.

new Graph

Creates an empty in-memory RDF graph.

Graph#add(Triple triple)

Adds a triple to the Graph, if it doesn't already exist.


Adds the given graph or array of Triple instances to the Graph.

Graph#remove(Triple triple)

Removes the given triple from the Graph, if it exists.

Graph#removeMatches(subject, predicate, object)

Removes the given triple from the Graph, if it exists.


Returns an array of Triples currently in the Graph.

Graph#some(function callback)

Same behavior as Array#some: Evaluates callback over each Triple in the Graph, and returns true if the callback returns truthy for any of them.

Graph#every(function callback)

Same behavior as Array#every: Evaluates callback over each Triple in the Graph, and returns true if the callback returns truthy for all of them.

Graph#filter(function callback)

Same behavior as Array#filter: Evaluates callback over each Triple in the Graph, and returns a Graph with the triples that evaluated truthy.

Graph#forEach(function callback)

Same behavior as Array#forEach: Evaluates callback over each Triple in the Graph.


Determines if the provided graph is isomorphic with the current one: Determines if all the Literal and NamedNode instances equal, and is there a one-to-one mapping of bnodes between the two graphs. If so, it returns the mapping, the toString blanknode as the key, the graph argument's BlankNode instance as value. If there's no match, it returns null.


Returns a new Graph that's the concatenation of this graph with the argument.


Returns a ResultSet, a pointer to a node in a graph that can be walked to query for data.

The provided resource does not necessarily have to exist in the graph, however, any operations on it will produce an empty set.


Represents a set of RDF Quad instances.

This implements most of the RDF/JS: Dataset specification, using six indexes for fast querying.

Instances of Dataset are uniquely identified by their instance. Datasets are mutable. Methods with a return value are pure, non-pure (mutating) methods always return undefined.


Represents a variable for subgraph matching, in e.g. SPARQL queries. This is also an instance of RDFNode.

A Variable instance may be used in a TriplePattern instance. Instances are not allowed in Triple statements, since they're for subgraph matching, and not actual graph data.


Represents a node in an instance of a graph, whose relationships inside the graph can be walked and then queried. This is called ResultSet instead of NodeSet because it also contains a pointer to the graph of data and other nodes that can be walked.


  • ResultSet#length - provides the size of the set


Walks the predicate relationship over each node in the set, returning a new ResultSet with the destination nodes, and a reference to the same graph.

If the current set is an empty set, the return value will also be an empty set.

If any nodes in the current set are literals, they will be ignored and will not produce any destination nodes.


Walks the predicate relationship backwards from each node in the set, returning a new ResultSet with the destination nodes, and a reference to the same graph.

If the current set is an empty set, the return value will also be an empty set.

This method will walk backwards from Literal, destination nodes will be BlankNode or NamedNode.


Return the nodes in the set as an Array.

ResultSet#some(function callback)

Same behavior as Array#some: Evaluates callback over each RDFNode in the ResultSet, and returns true if the callback returns truthy for any of them.

ResultSet#every(function callback)

Same behavior as Array#every: Evaluates callback over each RDFNode in the ResultSet, and returns true if the callback returns truthy for all of them.

ResultSet#filter(function callback)

Same behavior as Array#filter: Evaluates callback over each RDFNode in the ResultSet, and returns a new ResultSet with the triples that evaluated truthy.

ResultSet#forEach(function callback)

Same behavior as Array#forEach: Evaluates callback over each RDFNode in the ResultSet.

ResultSet#map(function callback)

Same behavior as Array#map: Evaluates callback over each RDFNode in the ResultSet, and returns a new ResultSet of each of the returned triples.

ResultSet#reduce(function callback, any initial)

Same behavior as Array#reduce: Evaluates callback over each RDFNode in the ResultSet with the current node and the previous return value, or initial if the first item.


Returns the only item in the set if there is one, or null otherwise. Or else if there is more than one item in the set, throws an Error.


A variant of Triple that allows Variable instances in the subject, predicate, or object.


An implementation of the Data parser API of RDF Interfaces.

To synchronously parse a Turtle document, use TurtleParser.parse()

TurtleParser.parse(document, base)

Returns a TurtleParser that has processed document with given base.

The parsed Graph instance is available at TurtleParser#graph:

const parse = rdf.TurtleParser.parse('<http://example.com/> a <http://example.com/Page> .');

parse(object, id)

Returns an object generated by parsing the properties of object to create Triples about id. These can later be serialized to a Turtle document or a Graph.

The format is similar to JSON-LD, except strings are assumed to be IRIs or CURIEs by default. The @context, @vocab, @set, @list, and @id properties work as in JSON-LD.

The id argument, if provided, must be a fully qualified IRI, and should be a NamedNode or BlankNode.

parse(object, id).n3()

Returns a string that's a Turtle document parsed out of object.

parse(object, id).graphify()

Returns a Graph of the triples parsed out of object.


RDFEnvironment is the data factory that generates RDF nodes, graphs, and stores process-level prefix mappings.

It implements the RDF Environment API of RDF Interfaces.

The rdf module creates one such global environment by default, accessible at rdf.environment. Others are created where necessary, e.g. when parsing a Turtle document, and may be created using new rdf.RDFEnvironment.


The environment export is the default instance of RDFEnvironment.

Generally, you'll want to alias this to something:

const rdfenv = require('rdf').environment;



Returns an IRI factory, a function that produces an IRI of prefix plus the provided argument. It's a simple wrapper around string concatenation:

const foaf = rdf.ns('http://xmlns.com/foaf/0.1/');


Returns an IRI produced by appending name to the rdf: namespace, http://www.w3.org/1999/02/22-rdf-syntax-ns#.


Returns an IRI produced by appending name to the rdfs: namespace, http://www.w3.org/2000/01/rdf-schema#.


Returns an IRI produced by appending name to the xsd: namespace, http://www.w3.org/2001/XMLSchema#.


Instead of using NamedNode, URIs by default are represented as plain strings. The RDFNode interface may be overloaded onto the standard String object using rdf.setBuiltins() or onto a particular prototype by using:


as done in the setBuiltins function call in lib/Builtins.js.

This extends the prototype definitions to act as native RDF types as well, for example:

true.toNT();         // "true"^^<http://www.w3.org/2001/XMLSchema#boolean>
(12 * 1.4).toNT();   // "12.3"^^<http://www.w3.org/2001/XMLSchema#decimal>

Object Builtins

Any two values may be compared with each other using the equals method:

(true).equals(rdf.environment.createLiteral('true', null, 'xsd:boolean'.resolve()) // true

The node type may be queried with the nodeType method:


An object may be assigned a URI and parsed for triples with the ref method:

var structure =
	{ 'dbp:dateOfBirth': '1879-03-14'.tl('xsd:date')
	, 'foaf:depictation': 'http://en.wikipedia.org/wiki/Image:Albert_Einstein_Head.jpg'

ref may be called without any argument to create a BlankNode.

The resulting object has a number of methods:

  • structure.n3() returns a Turtle/N3 document close to the original structure.
  • structure.toNT() returns an N-Triples formatted list of triples.
  • structure.graphify() returns an IndexedGraph of triples.

If multiple properties with the same predicate need to be added, put the multiple values in an Array:

{a: ['foaf:Person']}.ref()

An Array may also be used to make an RDF Collection (linked list), with the toList method:

['rdfs:Class', 'rdfs:Resource'].toList()

String Builtins

Strings may be used in place of a NamedNode and BlankNode, and have the same properties. There are the following methods:

  • tl(type) creates a typed literal out of the given value.
  • l(lang) creates a standard literal, with an optional language value.
  • resolve() resolves a CURIE/term to an IRI. Unlike the environment/profile method, this returns the original string if unsuccessful (for instance, if the string is already a URI).

URIs passed to these functions may be CURIEs and are resolved with the global rdf.environment.


A Mocha test suite is found in the tests directory. Run make test to evaluate the tests.

Index of Files

  • bin/turtle-equal.js - executable that determines of two Turtle files encode the same graph
  • bin/turtle-nt.js - executable that prints an N-Triples document of the triples found in the listed Turtle files
  • index.js - exposed module entry point
  • lib/ - additional library files imported by index.js
  • Makefile - Downloads and runs test suite
  • package.json - some metadata about this package
  • README.md - You're looking at it
  • README.ipynb - Sources for execution results in README.md
  • test/*.test.js - Mocha test suite files
  • test/graph-test-lib.js - A generic test for a Graph interface
  • test/TurtleTests/ - Tests from the Turtle test suite are extracted here
  • UNLICENSE - Public Domain dedication

Package Sidebar


npm i rdf

Weekly Downloads






Unpacked Size

387 kB

Total Files


Last publish


  • acubed