diff --git a/README.md b/README.md index cf5e554d..478a984d 100644 --- a/README.md +++ b/README.md @@ -199,6 +199,12 @@ To write N-Triples (or N-Quads) instead, pass a `format` argument upon creation const writer1 = new N3.Writer({ format: 'N-Triples' }); const writer2 = new N3.Writer({ format: 'application/trig' }); ``` +To exclude the graph name from the serialization, pass a `graphs` argument upon creation: +```JavaScript +const writer3 = new N3.Writer({ graphs: 'keep' }); // Keeps the graph names (default) +const writer4 = new N3.Writer({ graphs: 'drop' }); // Drops the graph name +const writer5 = new N3.Writer({ graphs: 'error' }); // Throws an error when writing a graph name +``` ### From quads to an RDF stream diff --git a/src/N3Writer.js b/src/N3Writer.js index abc3852f..6dccc1be 100644 --- a/src/N3Writer.js +++ b/src/N3Writer.js @@ -35,6 +35,9 @@ export default class N3Writer { options = outputStream, outputStream = null; options = options || {}; this._lists = options.lists; + this._keepGraphs = !options.graphs || options.graphs === 'keep'; + this._errorOnGraphs = options.graphs === 'error'; + // If no output stream given, send the output as string through the end callback if (!outputStream) { @@ -84,8 +87,11 @@ export default class N3Writer { // ### `_writeQuad` writes the quad to the output stream _writeQuad(subject, predicate, object, graph, done) { try { + if (this._errorOnGraphs && !DEFAULTGRAPH.equals(graph)) { + done(new Error('The chosen serialization settings do not support triples in a non-default graph.')); + } // Write the graph's label if it has changed - if (!graph.equals(this._graph)) { + if (this._keepGraphs && !graph.equals(this._graph)) { // Close the previous graph and start the new one this._write((this._subject === null ? '' : (this._inDefaultGraph ? '.\n' : '\n}\n')) + (DEFAULTGRAPH.equals(graph) ? '' : `${this._encodeIriOrBlank(graph)} {\n`)); @@ -117,15 +123,20 @@ export default class N3Writer { _writeQuadLine(subject, predicate, object, graph, done) { // Write the quad without prefixes delete this._prefixMatch; - this._write(this.quadToString(subject, predicate, object, graph), done); + this._write(this.quadToString(subject, predicate, object, graph, done), done); } // ### `quadToString` serializes a quad as a string - quadToString(subject, predicate, object, graph) { + quadToString(subject, predicate, object, graph, done) { + if (this._errorOnGraphs && !DEFAULTGRAPH.equals(graph)) { + const error = new Error('The chosen serialization settings do not support triples in a non-default graph.'); + if (done) return done(error); + throw error; + } return `${this._encodeSubject(subject)} ${ this._encodeIriOrBlank(predicate)} ${ this._encodeObject(object) - }${graph && graph.value ? ` ${this._encodeIriOrBlank(graph)} .\n` : ' .\n'}`; + }${this._keepGraphs && graph && graph.value ? ` ${this._encodeIriOrBlank(graph)} .\n` : ' .\n'}`; } // ### `quadsToString` serializes an array of quads as a string diff --git a/test/N3Writer-test.js b/test/N3Writer-test.js index 33660145..54f01a17 100644 --- a/test/N3Writer-test.js +++ b/test/N3Writer-test.js @@ -31,6 +31,17 @@ describe('Writer', () => { const writer = new Writer(); writer.quadToString(new NamedNode('a'), new NamedNode('b'), new NamedNode('c'), new NamedNode('g')).should.equal(' .\n'); }); + it('should throw error when it\'s forbidden to pass graphname', done => { + const writer = new Writer({ graphs: 'error' }); + try { + writer.quadToString(new NamedNode('a'), new NamedNode('b'), new NamedNode('c'), new NamedNode('g')).should.equal(' .\n'); + } + catch (error) { + error.should.be.an.instanceof(Error); + error.should.have.property('message', 'The chosen serialization settings do not support triples in a non-default graph.'); + done(); + } + }); it('should serialize an array of triples', () => { const writer = new Writer(); @@ -656,6 +667,57 @@ describe('Writer', () => { }); }); + it('ignores the graph name when needed in N-Quads mode', done => { + const writer = new Writer({ graphs: 'ignore', format: 'n-quads' }); + writer.addQuad(new Quad( + new NamedNode('a:a'), + new NamedNode('b:b'), + new NamedNode('c:c'), + new NamedNode('g:g'))); + writer.end((error, output) => { + output.should.equal(' .\n'); + done(error); + }); + }); + + it('throws an graph-found error needed in N-Quads mode', done => { + const writer = new Writer({ graphs: 'error', format: 'n-quads' }); + writer.addQuad(new Quad( + new NamedNode('a:a'), + new NamedNode('b:b'), + new NamedNode('c:c'), + new NamedNode('g:g')), error => { + error.should.be.an.instanceof(Error); + error.should.have.property('message', 'The chosen serialization settings do not support triples in a non-default graph.'); + done(); + }); + }); + it('ignores the graph name when needed', done => { + const writer = new Writer({ graphs: 'ignore' }); + writer.addQuad(new Quad( + new NamedNode('a:a'), + new NamedNode('b:b'), + new NamedNode('c:c'), + new NamedNode('g:g'))); + writer.end((error, output) => { + output.should.equal(' .\n'); + done(error); + }); + }); + + it('throws an graph-found error needed', done => { + const writer = new Writer({ graphs: 'error' }); + writer.addQuad(new Quad( + new NamedNode('a:a'), + new NamedNode('b:b'), + new NamedNode('c:c'), + new NamedNode('g:g')), error => { + error.should.be.an.instanceof(Error); + error.should.have.property('message', 'The chosen serialization settings do not support triples in a non-default graph.'); + done(); + }); + }); + it('should end when the end option is not set', done => { const outputStream = new QuickStream(), writer = new Writer(outputStream, {}); outputStream.should.have.property('ended', false);