Standalone RDF 1.2 interchange toolkit. It reversibly converts RDF dataset
quads to ordinary rdf/4 Prolog facts and ground rdf/4 facts back to RDF,
and does the same for eyecode documents.
The package contains no Prolog solver.
RDF supplies the data model; ISO Prolog supplies the programming language. This package connects them with two converters and a small term mapping:
rdf/4 facts.rdf/4 facts and convert them back to RDF.The mapping guide explains the representation and its practical
limits. Why RDF and Prolog? explains the choice of tools.
prolog-to-rdf reads facts without executing rules or directives. The
converter preserves quads, but cannot preserve empty named graphs, which
have no quads to encode.
Its vendored source parser is synchronized with EyeProlog’s parser while using
a minimal standalone term model. See EXTRACTION.md for the
source revision and the intentionally small adaptation boundary.
npm install
Node.js 18+ is required. N-Quads/N-Triples use the built-in parser. rdf-parse
is an optional dependency for Turtle, TriG, JSON-LD, RDF/XML, RDFa, and other
RDF syntaxes.
rdf-to-prolog data.ttl -o data.pl
prolog-to-rdf data.pl -o roundtripped.ttl
The Prolog representation is:
rdf(Subject, Predicate, Object, Graph).
prolog-to-rdf infers its output syntax from .nq, .ttl, or .trig (or use
--format nq|ttl|trig).
examples/ contains 14 flat, complete examples. Every example has exactly the
same five-file shape:
examples/<name>-input.ttl|trig
examples/<name>-input.pl
examples/<name>-rules.pl
examples/<name>-output.pl
examples/<name>-output.ttl|trig
The meaning is literal:
RDF input
| rdf-to-prolog
v
<name>-input.pl
+ <name>-rules.pl (Prolog)
| query result_rdf/4
v
<name>-output.pl (ground rdf/4 test results)
| prolog-to-rdf
v
RDF output
All rule files expose:
result_rdf(S, P, O, G).
write_results.
result_rdf/4 is the query used by these examples. write_results/0 prints
all its solutions as ground rdf/4 facts, the format accepted by
prolog-to-rdf. The converter also reads ground result_rdf/4 facts, so a
result document that lists the query’s answers as facts, such as eyepl’s
output, converts directly. Other query names need rdf/4 facts.
See examples/README.md for a concrete trust-flow run.
With EyeProlog 1.5.26 or newer, materialize those facts without adding the
resolved write_results goal to the output:
eyeprolog --quiet --goal write_results \
examples/odrl-dpv-fpv-trust-flow-input.pl \
examples/odrl-dpv-fpv-trust-flow-rules.pl \
> examples/odrl-dpv-fpv-trust-flow-output.pl
RDF -> Prolog:
rdf-to-prolog [options] input
--format TYPE input media type/extension when needed
--base IRI base IRI for relative references
--rules FILE append a rule file (optional convenience)
--include-source store input as source_rdf/4 and bridge it through rdf/4
--scope NAME blank-node scope
-o, --output FILE output file
Prolog -> RDF:
prolog-to-rdf [options] facts.pl
--format nq|ttl|trig RDF output syntax; otherwise inferred from -o
-o, --output FILE output file
prolog-to-rdf does not execute rules. A Prolog engine first materializes the
rule result as ground rdf/4 facts; the checked-in *-output.pl files show
exactly what that means.
Aliases rdf-to-pl and pl-to-rdf are also provided.
eyecode states rules in JavaScript
and reads data as documents of JavaScript expressions, one per line, which it
never executes. rdf-to-eyecode writes the same rdf/4 terms as such a
document, for eyecode’s facts_from, and eyecode-to-rdf reads the ground
rdf/4 and result_rdf/4 terms of an eyecode document, such as the
conclusions of a run, back as RDF:
rdf-to-eyecode data.ttl -o data.js
eyecode rules.js > results.js # rules.js loads facts_from('data.js')
eyecode-to-rdf results.js -o results.ttl
rdf-to-eyecode takes the input options of rdf-to-prolog except --rules
and --include-source, since rules belong in the eyecode program; and
eyecode-to-rdf takes the options of prolog-to-rdf. The terms differ from
the Prolog ones only in spelling: atoms are always quoted, as in
'default_graph' and lang('ar', 'rtl'), and no statement ends with a period.
A term skolem(Rule, Variable, Arguments) in an eyecode conclusion names
something a rule said exists. eyecode-to-rdf writes it as a blank node of
scope skolem labelled by the term’s canonical text, so the same rule firing
always gives the same node and different firings never share one.
import {
compileRdfDocumentToProlog,
compileRdfToProlog,
extractRdfFromProlog,
serializeRdfFromProlog,
compileRdfDocumentToEyecode,
serializeRdfFromEyecode,
} from 'rdf-interchange';
const facts = compileRdfToProlog(nquads);
const nquadsAgain = extractRdfFromProlog(facts);
const turtle = serializeRdfFromProlog(facts, { format: 'ttl' });
const document = await compileRdfDocumentToEyecode(turtle, { inputPath: 'data.ttl' });
const trig = serializeRdfFromEyecode(eyecodeConclusions, { format: 'trig' });
| RDF value | Prolog term |
|---|---|
| IRI | iri(Value) |
| Blank node | bnode(Scope, Label) |
| Typed literal | literal(Value, datatype(IRI)) |
| Language string | literal(Value, lang(Language)) |
| Directional language string | literal(Value, lang(Language, ltr)) / lang(Language, rtl) |
| RDF 1.2 triple term | triple(Subject, Predicate, Object) |
| Default graph | default_graph |
RDF textual values are represented by ISO Prolog atoms. The publisher rejects
Prolog strings and numbers in text positions instead of silently coercing
them. IRIs must be absolute, language tags must follow RDF syntax, and RDF 1.2
base direction must be ltr or rtl.
npm test
The example test discovers all 14 names from the flat directory, verifies the
five-file layout, roundtrips every checked-in input/output Prolog dataset,
and verifies that every *-output.ttl|trig is exactly the prolog-to-rdf
serialization of its matching *-output.pl. When rdf-parse is installed it
also regenerates each *-input.pl from the original Turtle/TriG source.