Skip to content

Commit e3b0d4e

Browse files
committed
Added proper support for usage of examples in cases of XML type of body
1 parent a9d2b9b commit e3b0d4e

File tree

9 files changed

+308
-654
lines changed

9 files changed

+308
-654
lines changed

lib/common/js2xml.js

Lines changed: 0 additions & 472 deletions
This file was deleted.

lib/schemaUtils.js

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ const { formatDataPath, checkIsCorrectType, isKnownType } = require('./common/sc
1313
deref = require('./deref.js'),
1414
_ = require('lodash'),
1515
xmlFaker = require('./xmlSchemaFaker.js'),
16-
js2xml = require('./common/js2xml.js'),
1716
openApiErr = require('./error.js'),
1817
ajvValidationError = require('./ajValidation/ajvValidationError'),
1918
utils = require('./utils.js'),
@@ -242,7 +241,7 @@ function safeSchemaFaker (oldSchema, resolveTo, resolveFor, parameterSourceOptio
242241

243242
try {
244243
if (schemaFormat === SCHEMA_FORMATS.XML) {
245-
fakedSchema = xmlFaker(null, resolvedSchema, indentCharacter);
244+
fakedSchema = xmlFaker(null, resolvedSchema, indentCharacter, resolveTo);
246245
schemaFakerCache[key] = fakedSchema;
247246
return fakedSchema;
248247
}
@@ -1607,15 +1606,27 @@ module.exports = {
16071606

16081607
// Convert example into XML if present as JSON data
16091608
if (contentType === TEXT_XML || contentType === APP_XML || headerFamily === HEADER_TYPE.XML) {
1610-
bodyData = js2xml(bodyData, indentCharacter);
1609+
let bodySchemaWithExample = bodyObj.schema;
1610+
1611+
// Assign example at schema level to be faked by xmlSchemaFaker
1612+
if (typeof bodyObj.schema === 'object') {
1613+
bodySchemaWithExample = Object.assign({}, bodyObj.schema, { example: bodyData });
1614+
}
1615+
bodyData = xmlFaker(null, bodySchemaWithExample, indentCharacter, resolveTo);
16111616
}
16121617
}
16131618
else if (!_.isEmpty(bodyObj.examples) && (resolveTo === 'example' || !bodyObj.schema)) {
16141619
// take one of the examples as the body and not all
16151620
bodyData = this.getExampleData(bodyObj.examples, components, options);
16161621

16171622
if (contentType === TEXT_XML || contentType === APP_XML || headerFamily === HEADER_TYPE.XML) {
1618-
bodyData = js2xml(bodyData, indentCharacter);
1623+
let bodySchemaWithExample = bodyObj.schema;
1624+
1625+
// Assign example at schema level to be faked by xmlSchemaFaker
1626+
if (typeof bodyObj.schema === 'object') {
1627+
bodySchemaWithExample = Object.assign({}, bodyObj.schema, { example: bodyData });
1628+
}
1629+
bodyData = xmlFaker(null, bodySchemaWithExample, indentCharacter, resolveTo);
16191630
}
16201631
}
16211632
else if (bodyObj.schema) {
@@ -1652,17 +1663,8 @@ module.exports = {
16521663
return '<Error: Spec size too large, skipping faking of schemas>';
16531664
}
16541665

1655-
if (
1656-
resolveTo === 'example' &&
1657-
_.get(bodyObj.schema, 'example') !== undefined &&
1658-
(contentType === TEXT_XML || contentType === APP_XML || headerFamily === HEADER_TYPE.XML)
1659-
) {
1660-
bodyData = js2xml(bodyObj.schema.example, indentCharacter);
1661-
}
1662-
else {
1663-
bodyData = safeSchemaFaker(bodyObj.schema || {}, resolveTo, PROCESSING_TYPE.CONVERSION, parameterSourceOption,
1664-
components, schemaFormat, schemaCache, options);
1665-
}
1666+
bodyData = safeSchemaFaker(bodyObj.schema || {}, resolveTo, PROCESSING_TYPE.CONVERSION, parameterSourceOption,
1667+
components, schemaFormat, schemaCache, options);
16661668
}
16671669
else {
16681670
// do not fake if the option is false

lib/xmlSchemaFaker.js

Lines changed: 44 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,17 @@
11
/* eslint-disable */
22
const _ = require('lodash');
33

4-
function convertSchemaToXML(name, schema, attribute, indentChar, indent) {
4+
function convertSchemaToXML(name, schema, attribute, indentChar, indent, resolveTo) {
55
var tagPrefix = '',
6-
cIndent = _.times(indent, _.constant(indentChar)).join('');
6+
cIndent = _.times(indent, _.constant(indentChar)).join(''),
7+
retVal = '';
8+
9+
if (typeof schema !== 'object') {
10+
return retVal;
11+
}
12+
13+
const schemaExample = schema.example;
14+
715
name = _.get(schema, 'xml.name', name || 'element');
816
if (_.get(schema, 'xml.prefix')) {
917
tagPrefix = schema.xml.prefix ? `${schema.xml.prefix}:` : '';
@@ -21,6 +29,11 @@ function convertSchemaToXML(name, schema, attribute, indentChar, indent) {
2129
else if (schema.type === 'number') {
2230
actualValue = '(number)';
2331
}
32+
33+
if (resolveTo === 'example' && typeof schemaExample !== 'undefined') {
34+
actualValue = schemaExample;
35+
}
36+
2437
if (attribute) {
2538
return actualValue;
2639
}
@@ -42,7 +55,14 @@ function convertSchemaToXML(name, schema, attribute, indentChar, indent) {
4255
retVal += ` xmlns${formattedTagPrefix}="${schema.xml.namespace}"`
4356
}
4457
_.forOwn(schema.properties, (value, key) => {
45-
propVal = convertSchemaToXML(key, value, _.get(value, 'xml.attribute'), indentChar, indent + 1);
58+
const currParentExample = _.get(schemaExample, key);
59+
60+
// override example value accoding to parent if exists
61+
if (typeof currParentExample !== 'undefined' && typeof value === 'object') {
62+
value.example = currParentExample;
63+
}
64+
65+
propVal = convertSchemaToXML(key, value, _.get(value, 'xml.attribute'), indentChar, indent + 1, resolveTo);
4666
if (_.get(value, 'xml.attribute')) {
4767
attributes.push(`${key}="${propVal}"`);
4868
}
@@ -66,8 +86,25 @@ function convertSchemaToXML(name, schema, attribute, indentChar, indent) {
6686
contents;
6787

6888
schemaItemsWithXmlProps.xml = schema.xml;
69-
contents = convertSchemaToXML(arrayElemName, schemaItemsWithXmlProps, false, indentChar, indent + extraIndent) +
70-
convertSchemaToXML(arrayElemName, schemaItemsWithXmlProps, false, indentChar, indent + extraIndent);
89+
90+
if (resolveTo === 'example' && Array.isArray(schemaExample)) {
91+
let arrContent = _.map(schemaExample, (elementExample) => {
92+
// assign current element as example to schema
93+
typeof schemaItemsWithXmlProps === 'object' && (schemaItemsWithXmlProps.example = elementExample);
94+
return convertSchemaToXML(arrayElemName, schemaItemsWithXmlProps, false, indentChar,
95+
indent + extraIndent, resolveTo);
96+
});
97+
98+
contents = _.join(arrContent, '');
99+
}
100+
else {
101+
let singleElementContent = convertSchemaToXML(arrayElemName, schemaItemsWithXmlProps, false, indentChar,
102+
indent + extraIndent, resolveTo);
103+
104+
// Atleast 2 items per array will be added asame as JSON schema faker
105+
contents = singleElementContent + singleElementContent;
106+
}
107+
71108
if (isWrapped) {
72109
return `\n${cIndent}<${tagPrefix}${name}>${contents}\n${cIndent}</${tagPrefix}${name}>`;
73110
}
@@ -78,9 +115,9 @@ function convertSchemaToXML(name, schema, attribute, indentChar, indent) {
78115
return retVal;
79116
}
80117

81-
module.exports = function(name, schema, indentCharacter) {
118+
module.exports = function(name, schema, indentCharacter, resolveTo) {
82119
// substring(1) to trim the leading newline
83-
return convertSchemaToXML(name, schema, false, indentCharacter, 0).substring(1);
120+
return convertSchemaToXML(name, schema, false, indentCharacter, 0, resolveTo).substring(1);
84121
};
85122
/*
86123
a = convertSchemaToXML('Person',{

libV2/schemaUtils.js

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ const schemaFaker = require('../assets/json-schema-faker'),
55
_ = require('lodash'),
66
mergeAllOf = require('json-schema-merge-allof'),
77
xmlFaker = require('./xmlSchemaFaker.js'),
8-
js2xml = require('../lib/common/js2xml'),
98
URLENCODED = 'application/x-www-form-urlencoded',
109
APP_JSON = 'application/json',
1110
APP_JS = 'application/javascript',
@@ -862,7 +861,7 @@ let QUERYPARAM = 'query',
862861

863862
try {
864863
if (schemaFormat === SCHEMA_FORMATS.XML) {
865-
return xmlFaker(null, resolvedSchema, indentCharacter);
864+
return xmlFaker(null, resolvedSchema, indentCharacter, parametersResolution);
866865
}
867866

868867
// for JSON, the indentCharacter will be applied in the JSON.stringify step later on
@@ -1143,7 +1142,14 @@ let QUERYPARAM = 'query',
11431142
const exampleData = example || getExampleData(context, examples);
11441143

11451144
if (bodyType === APP_XML || bodyType === TEXT_XML || headerFamily === HEADER_TYPE.XML) {
1146-
bodyData = js2xml(exampleData, indentCharacter);
1145+
let reqBodySchemaWithExample = requestBodySchema;
1146+
1147+
// Assign example at schema level to be faked by xmlSchemaFaker
1148+
if (typeof requestBodySchema === 'object') {
1149+
reqBodySchemaWithExample = Object.assign({}, requestBodySchema, { example: exampleData });
1150+
}
1151+
1152+
return xmlFaker(null, reqBodySchemaWithExample, indentCharacter, parametersResolution);
11471153
}
11481154
else {
11491155
bodyData = exampleData;
@@ -1157,7 +1163,7 @@ let QUERYPARAM = 'query',
11571163
}
11581164

11591165
if (bodyType === APP_XML || bodyType === TEXT_XML || headerFamily === HEADER_TYPE.XML) {
1160-
return xmlFaker(null, requestBodySchema, indentCharacter);
1166+
return xmlFaker(null, requestBodySchema, indentCharacter, parametersResolution);
11611167
}
11621168

11631169

libV2/xmlSchemaFaker.js

Lines changed: 37 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
/* eslint-disable */
22
const _ = require('lodash');
33

4-
function convertSchemaToXML(name, schema, attribute, indentChar, indent) {
4+
function convertSchemaToXML(name, schema, attribute, indentChar, indent, resolveTo) {
55
var tagPrefix = '',
66
cIndent = _.times(indent, _.constant(indentChar)).join(''),
77
retVal = '';
88

9+
const schemaExample = typeof schema === 'object' && (schema.example);
10+
911
name = _.get(schema, 'xml.name', name || 'element');
1012
if (_.get(schema, 'xml.prefix')) {
1113
tagPrefix = schema.xml.prefix ? `${schema.xml.prefix}:` : '';
@@ -23,6 +25,11 @@ function convertSchemaToXML(name, schema, attribute, indentChar, indent) {
2325
else if (schema.type === 'number') {
2426
actualValue = '(number)';
2527
}
28+
29+
if (resolveTo === 'example' && typeof schemaExample !== 'undefined') {
30+
actualValue = schemaExample;
31+
}
32+
2633
if (attribute) {
2734
return actualValue;
2835
}
@@ -44,7 +51,14 @@ function convertSchemaToXML(name, schema, attribute, indentChar, indent) {
4451
retVal += ` xmlns${formattedTagPrefix}="${schema.xml.namespace}"`
4552
}
4653
_.forOwn(schema.properties, (value, key) => {
47-
propVal = convertSchemaToXML(key, value, _.get(value, 'xml.attribute'), indentChar, indent + 1);
54+
const currParentExample = _.get(schemaExample, key);
55+
56+
// override example value accoding to parent if exists
57+
if (typeof currParentExample !== 'undefined' && typeof value === 'object') {
58+
value.example = currParentExample;
59+
}
60+
61+
propVal = convertSchemaToXML(key, value, _.get(value, 'xml.attribute'), indentChar, indent + 1, resolveTo);
4862
if (_.get(value, 'xml.attribute')) {
4963
attributes.push(`${key}="${propVal}"`);
5064
}
@@ -68,8 +82,25 @@ function convertSchemaToXML(name, schema, attribute, indentChar, indent) {
6882
contents;
6983

7084
schemaItemsWithXmlProps.xml = schema.xml;
71-
contents = convertSchemaToXML(arrayElemName, schemaItemsWithXmlProps, false, indentChar, indent + extraIndent) +
72-
convertSchemaToXML(arrayElemName, schemaItemsWithXmlProps, false, indentChar, indent + extraIndent);
85+
86+
if (resolveTo === 'example' && Array.isArray(schemaExample)) {
87+
let arrContent = _.map(schemaExample, (elementExample) => {
88+
// assign current element as example to schema
89+
typeof schemaItemsWithXmlProps === 'object' && (schemaItemsWithXmlProps.example = elementExample);
90+
return convertSchemaToXML(arrayElemName, schemaItemsWithXmlProps, false, indentChar,
91+
indent + extraIndent, resolveTo);
92+
});
93+
94+
contents = _.join(arrContent, '');
95+
}
96+
else {
97+
let singleElementContent = convertSchemaToXML(arrayElemName, schemaItemsWithXmlProps, false, indentChar,
98+
indent + extraIndent, resolveTo);
99+
100+
// Atleast 2 items per array will be added asame as JSON schema faker
101+
contents = singleElementContent + singleElementContent;
102+
}
103+
73104
if (isWrapped) {
74105
return `\n${cIndent}<${tagPrefix}${name}>${contents}\n${cIndent}</${tagPrefix}${name}>`;
75106
}
@@ -80,9 +111,9 @@ function convertSchemaToXML(name, schema, attribute, indentChar, indent) {
80111
return retVal;
81112
}
82113

83-
module.exports = function(name, schema, indentCharacter) {
114+
module.exports = function(name, schema, indentCharacter, resolveTo) {
84115
// substring(1) to trim the leading newline
85-
return convertSchemaToXML(name, schema, false, indentCharacter, 0).substring(1);
116+
return convertSchemaToXML(name, schema, false, indentCharacter, 0, resolveTo).substring(1);
86117
};
87118
/*
88119
a = convertSchemaToXML('Person',{

test/data/valid_openapi/xmlExample.yaml

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,32 @@ paths:
1414
requestBody:
1515
content:
1616
text/xml:
17-
example:
18-
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope">
19-
<soap:Body>
20-
<NumberToWords xmlns="http://www.dataaccess.com/webservicesserver">
21-
<ubiNum>500</ubiNum>
22-
</NumberToWords>
23-
</soap:Body>
24-
</soap:Envelope>
17+
schema:
18+
type: object
19+
properties:
20+
'xmlns:soap':
21+
type: string
22+
xml:
23+
attribute: true
24+
example: http://schemas.xmlsoap.org/soap/envelope
25+
body:
26+
type: object
27+
properties:
28+
NumberToWords:
29+
type: object
30+
properties:
31+
xmlns:
32+
type: string
33+
xml:
34+
attribute: true
35+
example: http://www.dataaccess.com/webservicesserver
36+
ubiNum:
37+
type: integer
38+
example: 500
39+
xml:
40+
name: soap:Body
41+
xml:
42+
name: soap:Envelope
2543
responses:
2644
"200":
2745
description: OK

0 commit comments

Comments
 (0)