Early developmentNot everything described here has shipped yet.

Skip to content

RDF Export

NeoWiki projects its data to RDF in its own vocabulary — the native projection. Each wiki page becomes a named graph holding its page metadata and its Subjects (one RDF resource each) with their Statements and Relations.

The model is specified in NativeRdfProjection.md; this page is the as-built reference for the export surface.

For an end-to-end example comparing the native and ontology-mapped output, see the Person-to-EDM worked example.

Configuration

SettingDefaultPurpose
$wgNeoWikiRdfBaseUrithe wiki's canonical URL ($wgCanonicalServer)Base URI under which all NeoWiki IRIs are minted.
$wgNeoWikiDereferenceSubjectsToDataTabtrueWhether a browser dereferencing a Subject IRI lands on the hosting page's Data tab row (true) or the plain page (false).

IRI scheme

All NeoWiki IRIs live under $base ($wgNeoWikiRdfBaseUri). Standard vocabulary (rdf:, rdfs:, xsd:, dcterms:) is used for standard concepts.

PrefixNamespaceUsed for
neo:$base/ontology/NeoWiki vocabulary terms (neo:Page, neo:Relation, neo:hasSubject, neo:source, …)
neo-subj:$base/entity/Subject IRIs (neo-subj:s1demo8aaaaaab5)
neo-prop:$base/prop/Property and Relation-type predicates (neo-prop:Has_author)
neo-schema:$base/schema/Schema classes (neo-schema:Person)
neo-rel:$base/relation/Relation node IRIs (neo-rel:r1demo8aaaaaaD6)
neo-page:$base/page/Page resource IRIs (neo-page:42) — the subject of the page-metadata triples

Each page's named-graph IRI is $base/graph/{projection}/page/{id}. The {projection} segment is native or a Mapping page name (e.g. EDM), encoded like the names below — see Ontology Mapping. The page resource IRI (neo-page:42) stays projection-independent and appears inside the triples.

Nothing is written to the default graph. Stores that fold their named graphs into it answer unscoped queries anyway — QLever always does, and Oxigraph does with --union-default-graph — and on a store that does not, a query reaches page data only through GRAPH. Scope each pattern by the graph holding it rather than wrapping a whole query in one GRAPH block: patterns sharing a block must match within a single page.

Property, Schema, and Relation-type names, and Relation-property keys, form the local part of their IRI: spaces become underscores (Has authorneo-prop:Has_author), and characters illegal in an IRI (%, < > " { } | ^ \, backtick, control characters) are percent-encoded. Non-ASCII Unicode is kept raw. Caveat: the space→underscore step collides when a name already contains an underscore — Has author and Has_author share the neo-prop:Has_author IRI, which the native projection accepts. The base URI is trusted admin config and is not encoded.

A url value projects as an IRI object (<https://…>); a value that is not a valid absolute IRI falls back to an xsd:anyURI literal, so nothing is lost. The other value types map to xsd datatypes: text/selectxsd:string, numberxsd:decimal (or xsd:integer when fractionless), booleanxsd:boolean, datexsd:date, dateTimexsd:dateTime. Extensions map their own property types via addRdfValueMapper. A Statement whose property type has no registered mapper — including an unregistered type — is omitted from the projection.

A Subject whose Schema cannot be loaded (for example, its Schema page was deleted) is omitted from the projection; a warning is logged for each.

Endpoint

RDF is served per page or per Subject. Both take the same projection and format query parameters. projection selects the vocabulary: native (the default, described here) or the name of a Mapping page — see Ontology Mapping; an unknown projection returns 400. format picks the serialization, falling back to the Accept header, then to TriG; a value other than trig or turtle returns 400:

formatAcceptContent-TypeNamed graph
trig (default)application/trigapplication/trig; charset=utf-8yes
turtletext/turtletext/turtle; charset=utf-8no (same triples, no graph wrapper)

Responses carry Content-Disposition: inline with a filename of the page or Subject ID plus the format's extension (42.trig, 42.ttl).

Both endpoints and the concept-URI negotiator answer one indistinguishable 404 when the page or Subject does not exist, the caller may not read it, or NeoWiki cannot describe it; a malformed Subject ID returns 400.

Page

GET /rest.php/neowiki/v0/page/{pageId}/rdf

Returns the page's projection: its page metadata and every Subject on it, in the page's named graph. Under the native projection, a page holding no Subjects projects to its page metadata alone; an ontology projection emits no page metadata at all, so the same page projects to an empty graph — a 200, not a 404.

sh
curl 'https://wiki.example/rest.php/neowiki/v0/page/42/rdf?format=turtle'

Subject

GET /rest.php/neowiki/v0/subject/{subjectId}/rdf

Returns one Subject's projection: exactly the triples the page export emits for that Subject — its description, including the native relation reification — with none of the page-metadata triples, in the hosting page's named graph. Inbound relations pointing at the Subject from elsewhere are not included.

A readable Subject whose Schema has no mapping for the requested ontology target projects to an empty graph — a 200, not a 404.

sh
curl 'https://wiki.example/rest.php/neowiki/v0/subject/s1demo8aaaaaab5/rdf?projection=EDM'

Dereferencing subject IRIs

Every Subject's neo-subj: IRI — $base/entity/{subjectId} — is a dereferenceable concept URI. A GET content-negotiates it and answers 303 See Other with an absolute Location:

AcceptRedirects to
application/trigthe Subject's TriG RDF (.../subject/{id}/rdf?format=trig)
text/turtlethe Subject's Turtle RDF (.../subject/{id}/rdf?format=turtle)
text/html, */*, absent, anything elsethe Subject's hosting page

TriG wins when both RDF types are acceptable; the RDF redirects use the native projection.

The default HTML target is that page's Data tab (/Example_Page/subjects) opened on the Subject's row. When $wgNeoWikiDereferenceSubjectsToDataTab is set to false, the target is the wiki page itself (/Example_Page).

The negotiator is always reachable at the REST path, which needs no server configuration:

sh
curl -H 'Accept: text/turtle' 'https://wiki.example/rest.php/neowiki/v0/entity/s1demo8aaaaaab5'

To make the bare neo-subj: IRI dereference, route /entity/{id} to that REST path with an internal proxy — a plain rewrite leaves the path unchanged, so MediaWiki's REST router never matches it. The dev image ships this on Apache (mod_proxy + mod_proxy_http); its /w/ is the dev image's $wgScriptPath, which a different install replaces with its own rest.php path:

apache
RewriteRule ^/?entity/(.+)$ http://127.0.0.1/w/rest.php/neowiki/v0/entity/$1 [P,L]

This applies when $wgNeoWikiRdfBaseUri is the wiki's own host (the default); an external or institutional base URI is the operator's own routing concern.

Finding these exports

These exports are surfaced in the UI. The Data tab links to each Subject's JSON and per-projection Turtle/TriG, and the same for the whole page. Content pages that exist also emit <link rel="alternate"> autodiscovery tags (Turtle and TriG, native projection) in the HTML head, on a wiki with a graph database configured.

Bulk dump

maintenance/DumpRdf.php streams the projection of every page on the wiki to stdout as TriG, one named graph per page. Progress goes to stderr. It defaults to the native projection; --projection=<name> selects an ontology projection by its Mapping page name (see Ontology Mapping).

sh
php maintenance/run.php NeoWiki:DumpRdf > dump.trig
php maintenance/run.php NeoWiki:DumpRdf --projection=EDM > dump-edm.trig

Not covered here

  • SPARQL store and live sync (the projection feeds them, but they are a separate concern).
  • RDF import.
  • RDFS/OWL self-description of Schemas.