link-rdflib
Version:
an RDF library for node.js, patched for speed.
193 lines (160 loc) • 5.06 kB
JavaScript
module.exports = parse;
var jsonld = require('jsonld');
var N3 = require('n3'); // @@ Goal: remove this dependency
var NQuadsParser = require('n-quads-parser');
var N3Parser = require('./n3parser');
var parseRDFaDOM = require('./rdfaparser').parseRDFaDOM;
var RDFParser = require('./rdfxmlparser');
var sparqlUpdateParser = require('./patch-parser');
var BlankNode = require('./blank-node');
var NamedNode = require('./named-node');
var Literal = require('./literal');
var Util = require('./util');
/**
* Parse a string and put the result into the graph kb.
* Normal method is sync.
* Unfortunately jsdonld is currently written to need to be called async.
* Hence the mess below with executeCallback.
*/
function parse(str, kb, base, contentType, callback) {
contentType = contentType || 'text/turtle';
contentType = contentType.split(';')[0];
try {
if (contentType === 'text/n3' || contentType === 'text/turtle') {
var p = N3Parser(kb, kb, base, base, null, null, '', null);
p.loadBuf(str);
executeCallback();
} else if (contentType === 'application/nquads' || contentType === 'application/n-quads' || contentType === 'application/n-triples') {
var nqParser = new NQuadsParser(kb);
nqParser.loadBuf(str);
executeCallback();
} else if (contentType === 'application/rdf+xml') {
var parser = new RDFParser(kb);
parser.parse(Util.parseXML(str), base, kb.sym(base));
executeCallback();
} else if (contentType === 'application/xhtml+xml') {
parseRDFaDOM(Util.parseXML(str, {
contentType: 'application/xhtml+xml'
}), kb, base);
executeCallback();
} else if (contentType === 'text/html') {
parseRDFaDOM(Util.parseXML(str, {
contentType: 'text/html'
}), kb, base);
executeCallback();
} else if (contentType === 'application/sparql-update') {
// @@ we handle a subset
sparqlUpdateParser(str, kb, base);
executeCallback();
} else if (contentType === 'application/ld+json') {
var n3Parser = N3.Parser();
var triples = [];
if (contentType === 'application/ld+json') {
var jsonDocument;
try {
jsonDocument = JSON.parse(str);
} catch (parseErr) {
return callback(parseErr, null);
}
jsonld.toRDF(jsonDocument, {
format: 'application/nquads',
base: base
}, nquadCallback);
} else {
nquadCallback(null, str);
}
} else {
throw new Error("Don't know how to parse " + contentType + ' yet');
}
} catch (e) {
executeErrorCallback(e);
}
parse.handled = {
'text/n3': true,
'text/turtle': true,
'application/rdf+xml': true,
'application/xhtml+xml': true,
'text/html': true,
'application/sparql-update': true,
'application/ld+json': true,
'application/nquads': true,
'application/n-quads': true
};
function executeCallback() {
if (callback) {
callback(null, kb);
} else {
return;
}
}
function executeErrorCallback(e) {
if (contentType !== 'application/ld+json' || contentType !== 'application/nquads' || contentType !== 'application/n-quads') {
if (callback) {
callback(e, kb);
} else {
throw new Error('Error trying to parse <' + base + '> as ' + contentType + ':\n' + e + ':\n' + e.stack);
}
}
}
/*
function setJsonLdBase (doc, base) {
if (doc instanceof Array) {
return
}
if (!('@context' in doc)) {
doc['@context'] = {}
}
doc['@context']['@base'] = base
}
*/
function nquadCallback(err, nquads) {
if (err) {
callback(err, kb);
}
try {
n3Parser.parse(nquads, tripleCallback);
} catch (err) {
callback(err, kb);
}
}
function tripleCallback(err, triple, prefixes) {
if (err) {
callback(err, kb);
}
if (triple) {
triples.push(triple);
} else {
for (var i = 0; i < triples.length; i++) {
addTriple(kb, triples[i]);
}
callback(null, kb);
}
}
function addTriple(kb, triple) {
var subject = createTerm(triple.subject);
var predicate = createTerm(triple.predicate);
var object = createTerm(triple.object);
var why = null;
if (triple.graph) {
why = createTerm(triple.graph);
}
kb.add(subject, predicate, object, why);
}
function createTerm(termString) {
var value;
if (N3.Util.isLiteral(termString)) {
value = N3.Util.getLiteralValue(termString);
var language = N3.Util.getLiteralLanguage(termString);
var datatype = NamedNode.find(N3.Util.getLiteralType(termString));
return Literal.find(value, language, datatype);
} else if (N3.Util.isIRI(termString)) {
return NamedNode.find(termString);
} else if (N3.Util.isBlank(termString)) {
value = termString.substring(2, termString.length);
return BlankNode.find(value);
} else {
return null;
}
}
}
;