Skip to content

Commit c359965

Browse files
author
Chris Wiechmann
committed
Added support to JSON2XML
1 parent b724a40 commit c359965

File tree

9 files changed

+603
-6311
lines changed

9 files changed

+603
-6311
lines changed

api-builder-plugin-fn-xml-node/package-lock.json

Lines changed: 322 additions & 6303 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

api-builder-plugin-fn-xml-node/src/flow-nodes.yml

Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,145 @@ flow-nodes:
7373
{ type: 'string' },
7474
{ type: 'object' }
7575
]
76+
throws:
77+
name: Error
78+
description: Failed to create JSON-String / JS-Object
79+
context: $.error
80+
schema:
81+
type: object
82+
properties:
83+
message:
84+
type: string
85+
86+
json2xml:
87+
name: JSON to XML
88+
description: Converts JSON payload into XML.
89+
parameters:
90+
jsonData:
91+
name: JSON Input data
92+
description: 'JSON Data.'
93+
required: true
94+
initialType: string
95+
schema:
96+
type: string
97+
asString:
98+
name: As string
99+
description: Wether return the JSON as String or as an Object. Defaults to false.
100+
required: false
101+
initialType: boolean
102+
schema:
103+
default: false
104+
type: boolean
105+
spaces:
106+
name: Spaces
107+
description: 'Number of spaces to be used for indenting XML output. Passing characters like " " or "\t" are also accepted.'
108+
group: Standard Options
109+
required: false
110+
initialType: number
111+
schema:
112+
default: 0
113+
oneOf:
114+
- type: number
115+
- type: string
116+
compact:
117+
name: Compact
118+
description: 'Whether the input object is in compact form or not. By default, input is expected to be in compact form. IMPORTANT: Remember to set this option compact: false if you are supplying non-compact json.'
119+
group: Standard Options
120+
required: false
121+
initialType: boolean
122+
schema:
123+
default: true
124+
type: boolean
125+
fullTagEmptyElement:
126+
name: Full tag empty element
127+
description: 'Whether to produce element without sub-elements as full tag pairs <a></a> rather than self closing tag <a/>'
128+
group: Advanced
129+
required: false
130+
initialType: boolean
131+
schema:
132+
default: false
133+
type: boolean
134+
indentCdata:
135+
name: Indent CDATA
136+
description: 'Whether to write CData in a new line and indent it. Will generate <a>\n <![CDATA[foo]]></a> instead of <a><![CDATA[foo]]></a>'
137+
group: Advanced
138+
required: false
139+
initialType: boolean
140+
schema:
141+
default: false
142+
type: boolean
143+
indentAttributes:
144+
name: Indent attributes
145+
description: 'Whether to print attributes across multiple lines and indent them (when spaces is not 0)'
146+
group: Advanced
147+
required: false
148+
initialType: boolean
149+
schema:
150+
default: false
151+
type: boolean
152+
ignoreDeclaration:
153+
name: Ignore declaration
154+
description: 'Whether to ignore writing declaration directives of xml. For example, <?xml?> will be ignored.'
155+
group: Advanced
156+
required: false
157+
initialType: boolean
158+
schema:
159+
default: false
160+
type: boolean
161+
ignoreInstruction:
162+
name: Ignore instruction
163+
description: 'Whether to ignore writing processing instruction of xml. For example, <?go there?> will be ignored.'
164+
group: Advanced
165+
required: false
166+
initialType: boolean
167+
schema:
168+
default: false
169+
type: boolean
170+
ignoreComment:
171+
name: Ignore comment
172+
description: 'Whether to ignore writing comments of the elements. That is, no <!-- --> will be generated.'
173+
group: Advanced
174+
required: false
175+
initialType: boolean
176+
schema:
177+
default: false
178+
type: boolean
179+
ignoreCdata:
180+
name: Ignore CDATA
181+
description: 'Whether to ignore writing CData of the elements. That is, no <![CDATA[ ]]> will be generated.'
182+
group: Advanced
183+
required: false
184+
initialType: boolean
185+
schema:
186+
default: false
187+
type: boolean
188+
ignoreDoctype:
189+
name: Ignore doctype
190+
description: 'Whether to ignore writing Doctype of the elements. That is, no <!DOCTYPE > will be generated.'
191+
group: Advanced
192+
required: false
193+
initialType: boolean
194+
schema:
195+
default: false
196+
type: boolean
197+
ignoreText:
198+
name: Ignore text
199+
description: 'Whether to ignore writing texts of the elements. For example, hi text in <a>hi</a> will be ignored.'
200+
group: Advanced
201+
required: false
202+
initialType: boolean
203+
schema:
204+
default: false
205+
type: boolean
206+
returns:
207+
name: Next
208+
description: Created XML data
209+
context: $.xmlData
210+
schema:
211+
oneOf: [
212+
{ type: 'string' },
213+
{ type: 'object' }
214+
]
76215
throws:
77216
name: Error
78217
description: Failed to create JSON-String / JS-Object

api-builder-plugin-fn-xml-node/src/index.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
const path = require('path');
22
const { SDK } = require('@axway/api-builder-sdk');
3-
const xmlToJson = require('./xmlToJson');
3+
const { xml2json } = require('./xml2Json');
4+
const { json2xml } = require('./json2Xml');
45

56
/**
67
* Resolves the API Builder plugin.
@@ -14,7 +15,7 @@ const xmlToJson = require('./xmlToJson');
1415
*/
1516
async function getPlugin(pluginConfig, options) {
1617
const sdk = new SDK({ pluginConfig });
17-
sdk.load(path.resolve(__dirname, 'flow-nodes.yml'), xmlToJson);
18+
sdk.load(path.resolve(__dirname, 'flow-nodes.yml'), { xml2json, json2xml });
1819
return sdk.getPlugin();
1920
}
2021

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
const convert = require('xml-js');
2+
var jp = require('jsonpath');
3+
/**
4+
* Action method.
5+
*
6+
* @param {object} params - A map of all the parameters passed from the flow.
7+
* @param {object} options - The additional options provided from the flow
8+
* engine.
9+
* @param {object} options.pluginConfig - The service configuration for this
10+
* plugin from API Builder config.pluginConfig['api-builder-plugin-pluginName']
11+
* @param {object} options.logger - The API Builder logger which can be used
12+
* to log messages to the console. When run in unit-tests, the messages are
13+
* not logged. If you wish to test logging, you will need to create a
14+
* mocked logger (e.g. using `simple-mock`) and override in
15+
* `MockRuntime.loadPlugin`. For more information about the logger, see:
16+
* https://docs.axway.com/bundle/api-builder/page/docs/developer_guide/project/logging/index.html
17+
* @param {*} [options.pluginContext] - The data provided by passing the
18+
* context to `sdk.load(file, actions, { pluginContext })` in `getPlugin`
19+
* in `index.js`.
20+
* @return {*} The response value (resolves to "next" output, or if the method
21+
* does not define "next", the first defined output).
22+
*/
23+
async function json2xml(params, options) {
24+
const { jsonData, spaces, compact, fullTagEmptyElement, indentCdata, indentAttributes, ignoreDeclaration, ignoreInstruction, ignoreAttributes, ignoreComment, ignoreCdata, ignoreDoctype, ignoreText } = params;
25+
const { logger } = options;
26+
if (!jsonData) {
27+
throw new Error('Missing required parameter: jsonData');
28+
}
29+
debugger;
30+
31+
const json2xmlOptions = {
32+
spaces: spaces ? spaces : 0,
33+
compact: compact ? compact : true,
34+
fullTagEmptyElement: fullTagEmptyElement ? fullTagEmptyElement : false,
35+
indentCdata: indentCdata ? indentCdata : false,
36+
indentAttributes: indentAttributes ? indentAttributes : false,
37+
ignoreDeclaration: ignoreDeclaration ? ignoreDeclaration : false,
38+
ignoreInstruction: ignoreInstruction ? ignoreInstruction : false,
39+
ignoreAttributes: ignoreAttributes ? ignoreAttributes : false,
40+
ignoreComment: ignoreComment ? ignoreComment : false,
41+
ignoreDoctype: ignoreDoctype ? ignoreDoctype : false,
42+
ignoreCdata: ignoreCdata ? ignoreCdata : false,
43+
ignoreDoctype: ignoreDoctype ? ignoreDoctype : false,
44+
ignoreText: ignoreText ? ignoreText : false,
45+
};
46+
47+
let result;
48+
try {
49+
if(jsonData instanceof Object) {
50+
logger.debug('Converting given JSON Object into XML.');
51+
result = convert.js2xml(jsonData, json2xmlOptions);
52+
} else {
53+
logger.debug('Converting given JSON String into XML.');
54+
result = convert.json2xml(jsonData, json2xmlOptions);
55+
}
56+
} catch (e) {
57+
logger.error(e.message);
58+
throw new Error(`Failed to convert JSON into XML. Error: ${e.message}`);
59+
}
60+
61+
if (typeof result === 'undefined' || result == "") {
62+
throw new Error(`Failed to convert JSON into XML. Error: result is: ${result}`);
63+
}
64+
65+
return result;
66+
}
67+
68+
module.exports = {
69+
json2xml
70+
};
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
const { expect } = require('chai');
2+
const { MockRuntime } = require('@axway/api-builder-test-utils');
3+
const getPlugin = require('../src');
4+
5+
describe('json2xmlTest', () => {
6+
let plugin;
7+
let flowNode;
8+
beforeEach(async () => {
9+
plugin = await MockRuntime.loadPlugin(getPlugin);
10+
plugin.setOptions({ validateOutputs: true });
11+
flowNode = plugin.getFlowNode('xml-node');
12+
});
13+
14+
describe('#json2xml', () => {
15+
it('should error when missing required parameter', async () => {
16+
const { value, output } = await flowNode.json2xml({
17+
jsonData: null
18+
});
19+
20+
expect(value).to.be.instanceOf(Error)
21+
.and.to.have.property('message', 'Missing required parameter: jsonData');
22+
expect(output).to.equal('error');
23+
});
24+
25+
it('should convert JSON-Object into XML', async () => {
26+
var xmlMessage = require('fs').readFileSync('./test/testMessages/basic_message-no-attributes.xml', 'utf8');
27+
var jsonMessage = JSON.parse(require('fs').readFileSync('./test/testMessages/basic_message.json', 'utf8'));
28+
const { value, output } = await flowNode.json2xml({ jsonData: jsonMessage, spaces: '\t' });
29+
30+
expect(value).to.deep.equal(xmlMessage);
31+
expect(output).to.equal('next');
32+
});
33+
34+
it('should convert JSON-String into XML', async () => {
35+
var xmlMessage = require('fs').readFileSync('./test/testMessages/basic_message-no-attributes.xml', 'utf8');
36+
var jsonMessage = JSON.parse(require('fs').readFileSync('./test/testMessages/basic_message.json', 'utf8'));
37+
const { value, output } = await flowNode.json2xml({ jsonData: JSON.stringify(jsonMessage), spaces: '\t' });
38+
39+
expect(output).to.equal('next');
40+
expect(value).to.be.a('string');
41+
expect(value).to.deep.equal(xmlMessage);
42+
});
43+
44+
it('should fail with an invalid JSON structure', async () => {
45+
var jsonMessage = require('fs').readFileSync('./test/testMessages/invalid_message.json', 'utf8');
46+
const { value, output } = await flowNode.json2xml({ jsonData: jsonMessage });
47+
48+
expect(output).to.equal('error');
49+
expect(value).to.be.instanceOf(Error)
50+
.and.to.have.property('message');
51+
expect(value.message).to.include('Failed to convert JSON into XML. Error: The JSON structure is invalid');
52+
});
53+
});
54+
});
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
<note>
2+
<title>Happy</title>
3+
<todo>Work</todo>
4+
<todo>Play</todo>
5+
<aBoolean>false</aBoolean>
6+
</note>
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"note": {
3+
"title": "Happy",
4+
"todo": ["Work", "Play"],
5+
"aBoolean": "false"
6+
]
7+
}
8+

api-builder-plugin-fn-xml-node/test/xmlToJsonTest.js renamed to api-builder-plugin-fn-xml-node/test/xml2jsonTest.js

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ const { expect } = require('chai');
22
const { MockRuntime } = require('@axway/api-builder-test-utils');
33
const getPlugin = require('../src');
44

5-
describe('api-builder-plugin-fn-xml-node', () => {
5+
describe('xml2jsonTest', () => {
66
let plugin;
77
let flowNode;
88
beforeEach(async () => {
@@ -22,10 +22,6 @@ describe('api-builder-plugin-fn-xml-node', () => {
2222
// Ensure the flow-node matches the spec
2323
expect(flowNode.name).to.equal('XML');
2424
expect(flowNode.description).to.equal('Provides support to handle XML-Payload');
25-
expect(flowNode.icon).to.be.a('string');
26-
expect(flowNode.getMethods()).to.deep.equal([
27-
'xml2json'
28-
]);
2925
});
3026

3127
it('should define valid flow-nodes', () => {
@@ -36,7 +32,6 @@ describe('api-builder-plugin-fn-xml-node', () => {
3632

3733
describe('#xml2json', () => {
3834
it('should error when missing required parameter', async () => {
39-
// Invoke #hello with a non-number and check error.
4035
const { value, output } = await flowNode.xml2json({
4136
xmlData: null
4237
});

0 commit comments

Comments
 (0)