From 8c47110bd0028dc1889dd6199b080c3d310265cb Mon Sep 17 00:00:00 2001 From: Nicolas Thouvenin Date: Thu, 27 May 2021 21:09:40 +0200 Subject: [PATCH] improve xml-string --- packages/basics/src/xml-string.js | 22 ++++++++++---- packages/basics/test/xml-string.js | 48 ++++++++++++++++++++++++++++++ 2 files changed, 64 insertions(+), 6 deletions(-) diff --git a/packages/basics/src/xml-string.js b/packages/basics/src/xml-string.js index 534b98cc..7d8bbfc5 100644 --- a/packages/basics/src/xml-string.js +++ b/packages/basics/src/xml-string.js @@ -3,16 +3,25 @@ import XML from 'xml-mapping'; function XMLString(data, feed) { const rootElement = this.getParam('rootElement', 'items'); const contentElement = this.getParam('contentElement', 'item'); - const rootNamespace = this.getParam('rootNamespace', ''); - const attrNS = rootNamespace.length > 0 ? ` xmlns="${encodeURI(rootNamespace)}"` : ''; - const beginTag = rootElement.length > 0 ? `<${rootElement}${attrNS}>` : ''; - const endTag = rootElement.length > 0 ? `` : ''; if (this.isLast()) { + const endTag = rootElement.length > 0 ? `` : ''; if (endTag) feed.write(endTag); return feed.close(); } - if (this.isFirst() && beginTag) { - feed.write(beginTag); + if (this.isFirst()) { + const prologue = this.getParam('prologue', false) ? '\n' : ''; + const rootNamespace = [] + .concat(this.getParam('rootNamespace')) + .filter(Boolean) + .map((ns) => ns.replace('://', '§§§')) + .map((ns) => ns.split(':')) + .map((ns) => (ns[1] ? [`:${ns[0]}`, ns[1]] : ['', ns[0]])) + .map((ns) => [ns[0], ns[1].replace('§§§', '://').trim()]) + .reduce((prev, cur) => `${prev} xmlns${cur[0]}="${encodeURI(cur[1])}"`, ''); + const beginTag = rootElement.length > 0 ? `${prologue}<${rootElement}${rootNamespace}>` : ''; + if (beginTag) { + feed.write(beginTag); + } } feed.send(XML.dump({ [contentElement]: data })); } @@ -24,6 +33,7 @@ function XMLString(data, feed) { * @param {String} [rootElement=items] Root element name for the tag which start and close the feed * @param {String} [contentElement=item] Content element name for the tag which start and close each item * @param {String} [rootNamespace] Namespace for the root tag (xmlns=) + * @param {Boolean} [prologue=false] Add XML prologue { done(); }); }); + test('with default parameters and prologue', (done) => { + const output = []; + from([{ $t: 'a' }]) + .pipe(ezs('XMLString', { prologue: true })) + .pipe(ezs.catch()) + .on('error', done) + .on('data', (chunk) => output.push(chunk)) + .on('end', () => { + const res = output.join(''); + expect(res).toStrictEqual('\na'); + done(); + }); + }); + test('with default parameters and prologue', (done) => { + const output = []; + from([{ $t: 'a' }]) + .pipe(ezs('XMLString', { prologue: true })) + .pipe(ezs.catch()) + .on('error', done) + .on('data', (chunk) => output.push(chunk)) + .on('end', () => { + const res = output.join(''); + expect(res).toStrictEqual('\na'); + done(); + }); + }); + test('with custom parameters', (done) => { const output = []; from([{ $t: 'a', about: 'uid:1' }]) @@ -35,6 +62,27 @@ describe('XMLString', () => { done(); }); }); + test('with custom namespace', (done) => { + const output = []; + from([{ $t: 'a', about: 'uid:1' }]) + .pipe(ezs('XMLString', { + rootElement: 'RDF', + contentElement: 'Description', + rootNamespace: [ + 'http://www.w3.org/1999/02/22-rdf-syntax-ns#', + 'cc: http://creativecommons.org/ns#', + 'rdfs: http://www.w3.org/2000/01/rdf-schema#', + ], + })) + .pipe(ezs.catch()) + .on('error', done) + .on('data', (chunk) => output.push(chunk)) + .on('end', () => { + const res = output.join(''); + expect(res).toStrictEqual('a'); + done(); + }); + }); test('without root element', (done) => { const output = []; from([{ $t: 'a' }])