La bibliothèque N3.JS est une implémentation de la spécification RDF.JS de bas niveau qui vous permet de gérer facilement RDF en JavaScript. Il propose:
L'analyse et l'écriture est:
Pour Node.js, N3.JS est un package NPM.
$ npm install n3
const N3 = require ( 'n3' ) ;
N3.JS fonctionne de manière transparente dans les navigateurs via WebPack ou Browserify. Si vous n'êtes pas familier avec ces outils, vous pouvez lire WebPack: Création d'un bundle - démarrer ou introduction à Browserify . Vous devrez créer un "bundle UMD" et fournir un nom (par exemple avec l'option -s N3
dans Browserify).
Vous pouvez également le charger via CDN:
< script src =" https://unpkg.com/n3/browser/n3.min.js " > </ script >
N3.JS suit la spécification RDF.JS de bas niveau.
N3.DataFactory
vous donnera les fonctions d'usine pour créer des triplets et des quads:
const { DataFactory } = N3 ;
const { namedNode , literal , defaultGraph , quad } = DataFactory ;
const myQuad = quad (
namedNode ( 'https://ruben.verborgh.org/profile/#me' ) , // Subject
namedNode ( 'http://xmlns.com/foaf/0.1/givenName' ) , // Predicate
literal ( 'Ruben' , 'en' ) , // Object
defaultGraph ( ) , // Graph
) ;
console . log ( myQuad . termType ) ; // Quad
console . log ( myQuad . value ) ; // ''
console . log ( myQuad . subject . value ) ; // https://ruben.verborgh.org/profile/#me
console . log ( myQuad . object . value ) ; // Ruben
console . log ( myQuad . object . datatype . value ) ; // http://www.w3.org/1999/02/22-rdf-syntax-ns#langString
console . log ( myQuad . object . language ) ; // en
Dans le reste de ce document, nous traiterons également des «triples» et des «quads»: nous supposons qu'un quad est simplement un triple dans un graphique nommé ou par défaut.
N3.Parser
transforme le document Turtle, Trig, N-triples ou N-Quads en quads via un rappel:
const tomAndJerry = `PREFIX c: <http://example.org/cartoons#>
# Tom is a cat
c:Tom a c:Cat.
c:Jerry a c:Mouse;
c:smarterThan c:Tom.`
const parser = new N3 . Parser ( ) ;
parser . parse ( tomAndJerry ,
( error , quad , prefixes ) => {
if ( quad )
console . log ( quad ) ;
else
console . log ( "# That's all, folks!" , prefixes ) ;
} ) ;
Le premier argument du rappel est une valeur d'erreur facultative, la seconde est un quad. S'il n'y a plus de quads, le rappel est invoqué une dernière fois avec null
pour quad
et un hachage de préfixes comme troisième argument.
Alternativement, un objet peut être fourni, où onQuad
, onPrefix
et onComment
sont utilisés pour écouter quads
, prefixes
et comments
comme suit:
const parser = new N3 . Parser ( ) ;
parser . parse ( tomAndJerry , {
// onQuad (required) accepts a listener of type (quad: RDF.Quad) => void
onQuad : ( err , quad ) => { console . log ( quad ) ; } ,
// onPrefix (optional) accepts a listener of type (prefix: string, iri: NamedNode) => void
onPrefix : ( prefix , iri ) => { console . log ( prefix , 'expands to' , iri . value ) ; } ,
// onComment (optional) accepts a listener of type (comment: string) => void
onComment : ( comment ) => { console . log ( '#' , comment ) ; } ,
} ) ;
Si aucun rappel n'est fourni, l'analyse se produit de retour de manière synchrone un tableau de quads:
const parser = new N3 . Parser ( ) ;
// An array of resultant Quads
const quadArray = parser . parse ( tomAndJerry ) ;
Par défaut, N3.Parser
analyse un superset permissif de Turtle, Trig, N-Triples et N-Quads.
Pour une stricte compatibilité avec l'une de ces langues, passez un argument format
lors de la création:
const parser1 = new N3 . Parser ( { format : 'N-Triples' } ) ;
const parser2 = new N3 . Parser ( { format : 'application/trig' } ) ;
La notation3 (N3) n'est soutenue que par l'argument format
:
const parser3 = new N3 . Parser ( { format : 'N3' } ) ;
const parser4 = new N3 . Parser ( { format : 'Notation3' } ) ;
const parser5 = new N3 . Parser ( { format : 'text/n3' } ) ;
Il est possible de fournir l'IRI de base du document que vous souhaitez analyser. Cela se fait en passant un argument baseIRI
lors de la création:
const parser = new N3 . Parser ( { baseIRI : 'http://example.org/' } ) ;
Par défaut, N3.Parser
préfixera les étiquettes de nœuds vierges avec un préfixe b{digit}_
. Ceci est fait pour empêcher les collisions de nœuds vierges non apparentés ayant des étiquettes identiques. L'argument blankNodePrefix
Constructor peut être utilisé pour modifier le préfixe ou, s'il est défini sur une chaîne vide, désactiver complètement la préfixe:
const parser = new N3 . Parser ( { blankNodePrefix : '' } ) ;
N3.Parser
peut analyser les flux Node.js au fur et à mesure qu'ils grandissent, retournant les quads dès qu'ils sont prêts.
const parser = new N3 . Parser ( ) ,
rdfStream = fs . createReadStream ( 'cartoons.ttl' ) ;
parser . parse ( rdfStream , console . log ) ;
N3.StreamParser
est un flux Node.js et une implémentation RDF.js Sink. Cette solution est idéale si votre consommateur est plus lent, car les données source ne sont lues que lorsque le consommateur est prêt.
const streamParser = new N3 . StreamParser ( ) ,
rdfStream = fs . createReadStream ( 'cartoons.ttl' ) ;
rdfStream . pipe ( streamParser ) ;
streamParser . pipe ( new SlowConsumer ( ) ) ;
function SlowConsumer ( ) {
const writer = new require ( 'stream' ) . Writable ( { objectMode : true } ) ;
writer . _write = ( quad , encoding , done ) => {
console . log ( quad ) ;
setTimeout ( done , 1000 ) ;
} ;
return writer ;
}
Un événement prefix
dédié signale chaque préfixe avec des arguments prefix
et term
. Un événement comment
dédié peut être activé en définissant comments: true
dans le constructeur N3.StreamParser.
N3.Writer
sérialise les quads en tant que document RDF. Écrivez des quads via addQuad
.
const writer = new N3 . Writer ( { prefixes : { c : 'http://example.org/cartoons#' } } ) ; // Create a writer which uses `c` as a prefix for the namespace `http://example.org/cartoons#`
writer . addQuad ( quad (
namedNode ( 'http://example.org/cartoons#Tom' ) , // Subject
namedNode ( 'http://example.org/cartoons#name' ) , // Predicate
literal ( 'Tom' ) // Object
) ) ;
writer . end ( ( error , result ) => console . log ( result ) ) ;
Par défaut, N3.Writer
écrit Turtle (ou Trig si certains quads sont dans un graphique nommé).
Pour écrire à la place des n-triples (ou n-quads), passez un argument format
lors de la création:
const writer1 = new N3 . Writer ( { format : 'N-Triples' } ) ;
const writer2 = new N3 . Writer ( { format : 'application/trig' } ) ;
N3.Writer
peut également écrire des quads sur un flux Node.js via addQuad
.
const writer = new N3 . Writer ( process . stdout , { end : false , prefixes : { c : 'http://example.org/cartoons#' } } ) ;
writer . addQuad (
namedNode ( 'http://example.org/cartoons#Tom' ) , // Subject
namedNode ( 'http://www.w3.org/1999/02/22-rdf-syntax-ns#type' ) , // Predicate
namedNode ( 'http://example.org/cartoons#Cat' ) // Object
) ;
writer . addQuad ( quad (
namedNode ( 'http://example.org/cartoons#Tom' ) , // Subject
namedNode ( 'http://example.org/cartoons#name' ) , // Predicate
literal ( 'Tom' ) // Object
) ) ;
writer . end ( ) ;
N3.StreamWriter
est un flux node.js et une implémentation de swier rdf.js.
const streamParser = new N3 . StreamParser ( ) ,
inputStream = fs . createReadStream ( 'cartoons.ttl' ) ,
streamWriter = new N3 . StreamWriter ( { prefixes : { c : 'http://example.org/cartoons#' } } ) ;
inputStream . pipe ( streamParser ) ;
streamParser . pipe ( streamWriter ) ;
streamWriter . pipe ( process . stdout ) ;
Vous voudrez peut-être utiliser les notations […]
et énumérer (…)
de tortue et de trig. Cependant, un écrivain en streaming ne peut pas les créer automatiquement: les notations de raccourci ne sont possibles que si les nœuds vierges ou les têtes de liste ne sont pas utilisés plus tard, ce qui ne peut être déterminé que par conclusion à la fin du flux.
Les fonctions blank
et list
vous permettent de les créer manuellement à la place:
const writer = new N3 . Writer ( { prefixes : { c : 'http://example.org/cartoons#' ,
foaf : 'http://xmlns.com/foaf/0.1/' } } ) ;
writer . addQuad (
writer . blank (
namedNode ( 'http://xmlns.com/foaf/0.1/givenName' ) ,
literal ( 'Tom' , 'en' ) ) ,
namedNode ( 'http://www.w3.org/1999/02/22-rdf-syntax-ns#type' ) ,
namedNode ( 'http://example.org/cartoons#Cat' )
) ;
writer . addQuad ( quad (
namedNode ( 'http://example.org/cartoons#Jerry' ) ,
namedNode ( 'http://xmlns.com/foaf/0.1/knows' ) ,
writer . blank ( [ {
predicate : namedNode ( 'http://www.w3.org/1999/02/22-rdf-syntax-ns#type' ) ,
object : namedNode ( 'http://example.org/cartoons#Cat' ) ,
} , {
predicate : namedNode ( 'http://xmlns.com/foaf/0.1/givenName' ) ,
object : literal ( 'Tom' , 'en' ) ,
} ] )
) ) ;
writer . addQuad (
namedNode ( 'http://example.org/cartoons#Mammy' ) ,
namedNode ( 'http://example.org/cartoons#hasPets' ) ,
writer . list ( [
namedNode ( 'http://example.org/cartoons#Tom' ) ,
namedNode ( 'http://example.org/cartoons#Jerry' ) ,
] )
) ;
writer . end ( ( error , result ) => console . log ( result ) ) ;
N3.Store
vous permet de stocker des triplets en mémoire et de les trouver rapidement.
Dans cet exemple, nous créons un nouveau magasin et ajoutons les triplets :Pluto a :Dog.
et :Mickey a :Mouse
.
Ensuite, nous trouvons des triplets avec :Mickey
comme sujet.
const store = new N3 . Store ( ) ;
store . add (
quad (
namedNode ( 'http://ex.org/Pluto' ) ,
namedNode ( 'http://ex.org/type' ) ,
namedNode ( 'http://ex.org/Dog' )
)
) ;
store . add (
quad (
namedNode ( 'http://ex.org/Mickey' ) ,
namedNode ( 'http://ex.org/type' ) ,
namedNode ( 'http://ex.org/Mouse' )
)
) ;
// Retrieve all quads
for ( const quad of store )
console . log ( quad ) ;
// Retrieve Mickey's quads
for ( const quad of store . match ( namedNode ( 'http://ex.org/Mickey' ) , null , null ) )
console . log ( quad ) ;
Si vous utilisez plusieurs magasins, vous pouvez réduire la consommation de mémoire en leur permettant de partager un indice d'entité:
const entityIndex = new N3 . EntityIndex ( ) ;
const store1 = new N3 . Store ( [ ] , { entityIndex } ) ;
const store2 = new N3 . Store ( [ ] , { entityIndex } ) ;
Dataset
Ce magasin adhère à l'interface Dataset
qui expose les propriétés suivantes
Attributs:
size
- Un entier non négatif qui spécifie le nombre de quads dans l'ensemble.Méthodes:
add
- ajoute le quad spécifié à l'ensemble de données. Les quads existants, tels que définis dans Quad.equals
, seront ignorés.delete
- Supprime le quad spécifié de l'ensemble de données.has
- détermine si un ensemble de données comprend un certain quad.match
- Renvoie un nouvel ensemble de données composé de tous les quads dans l'instance actuelle correspondant aux arguments donnés.[Symbol.iterator]
- implémente le protocole d'itérateur pour permettre l'itération sur tous quads
de l'ensemble de données comme dans l'exemple ci-dessus. Le magasin met en œuvre les méthodes de manipulation suivantes en plus de l'interface Dataset
standard (documentation):
addQuad
pour insérer un quadaddQuads
pour insérer un tableau de quadsremoveQuad
pour supprimer un quadremoveQuads
pour supprimer un tableau de quadsremove
pour supprimer un flux de quadsremoveMatches
pour supprimer tous les quads correspondant au modèle donnédeleteGraph
pour supprimer tous les quads avec le graphique donnécreateBlankNode
renvoie un identifiant de nœud vierge inutiliséLe magasin fournit les méthodes de recherche suivantes (documentation):
match
Renvoie un flux et un générateur de quads correspondant au modèle donnégetQuads
renvoie un tableau de quads correspondant au modèle donnécountQuads
compte le nombre de quads correspondant au modèle donnéforEach
exécute un rappel sur tous les quads correspondantsevery
retourne si un rappel sur les quads correspondants renvoie toujours vraisome
renvoient si un rappel sur les quads correspondants renvoie true au moins une foisgetSubjects
renvoie un tableau de sujets uniques survenant dans les quads correspondantsforSubjects
exécute un rappel sur des sujets uniques survenant dans les quads correspondantsgetPredicates
renvoie un tableau de prédicats uniques qui se produisent dans le quad correspondantforPredicates
exécute un rappel sur les prédicats uniques qui se produisent dans les quads correspondantsgetObjects
renvoie un tableau d'objets uniques se produisant dans le quad correspondantforObjects
exécute un rappel sur des objets uniques survenant dans les quads correspondantsgetGraphs
renvoie un tableau de graphiques uniques se produisant dans le quad correspondantforGraphs
exécute un rappel sur des graphiques uniques survenant dans les quads correspondants N3.JS prend en charge le raisonnement comme suit:
import { Reasoner , Store , Parser } from 'n3' ;
const parser = new Parser ( { format : 'text/n3' } ) ;
const rules = `
{
?s a ?o .
?o <http://www.w3.org/2000/01/rdf-schema#subClassOf> ?o2 .
} => {
?s a ?o2 .
} .
`
const rulesDataset = new Store ( parser . parse ( rules ) ) ;
const dataset = new Store ( /* Dataset */ )
// Applies the rules to the store; mutating it
const reasoner = new Reasoner ( store ) ;
reasoner . reason ( rules ) ;
Remarque : N3.JS ne prend actuellement en charge que les règles avec les modèles de graphes de base dans la prémisse et la conclusion. Les intégrés et les déchets arrière ne sont pas pris en charge. Pour un raisonnement RDF / JS qui prend en charge toutes les fonctionnalités de raisonnement de Notation3, consultez Eye-JS.
L'analyseur et l'écrivain N3.JS sont entièrement compatibles avec les spécifications W3C suivantes:
De plus, l'analyseur N3.JS prend également en charge Notation3 (N3) (aucune spécification officielle pour le moment).
L'analyseur et l'écrivain N3.JS sont également entièrement compatibles avec les variantes RDF-Star des spécifications W3C.
Le mode par défaut est permissif et permet un mélange de différentes syntaxes, y compris RDF-Star. Passez une option format
au constructeur avec le nom ou le type MIME d'un format pour un comportement strict et intolérant. Si une chaîne de format contient star
ou *
(par exemple, turtlestar
ou TriG*
), la prise en charge RDF-Star pour ce format sera activée.
Les sous-modules N3.JS sont compatibles avec les interfaces RDF.JS suivantes:
N3.DataFactory
implémente DataFactory
Term
d'implémentation et l'un de NamedNode
, BlankNode
, Literal
, Variable
, DefaultGraph
Term
d'implémentation, Triple
et Quad
N3.StreamParser
implémente Stream
et Sink
N3.StreamWriter
implémente Stream
et Sink
N3.Store
implémente Store
Source
Sink
DatasetCore
La bibliothèque N3.JS est protégée par le droit d'auteur par Ruben Verborgh et libérée sous la licence du MIT.
Les contributions sont les bienvenues et les rapports de bogues ou les demandes de traction sont toujours utiles. Si vous prévoyez d'implémenter une fonctionnalité plus grande, il est préférable de me contacter en premier.