link-rdflib
Version:
an RDF library for node.js, patched for speed.
168 lines (158 loc) • 4.95 kB
JavaScript
module.exports = parse
const jsonld = require('jsonld')
const N3 = require('n3') // @@ Goal: remove this dependency
const NQuadsParser = require('n-quads-parser')
const N3Parser = require('./n3parser')
const parseRDFaDOM = require('./rdfaparser').parseRDFaDOM
const RDFParser = require('./rdfxmlparser')
const sparqlUpdateParser = require('./patch-parser')
const BlankNode = require('./blank-node')
const NamedNode = require('./named-node')
const Literal = require('./literal')
const 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') {
const 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},
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
}
}
}