soap 0.20.0 → 0.24.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. package/.editorconfig +23 -23
  2. package/.jshintrc +29 -29
  3. package/.travis.yml +22 -22
  4. package/CONTRIBUTING.md +52 -58
  5. package/History.md +52 -2
  6. package/LICENSE +7 -7
  7. package/PUBLISHING.md +28 -28
  8. package/Readme.md +1062 -931
  9. package/coverage/coverage.json +1 -0
  10. package/coverage/lcov-report/base.css +212 -0
  11. package/coverage/lcov-report/index.html +119 -0
  12. package/coverage/lcov-report/node-soap/index.html +93 -0
  13. package/coverage/lcov-report/node-soap/index.js.html +74 -0
  14. package/coverage/lcov-report/node-soap/lib/client.js.html +1001 -0
  15. package/coverage/lcov-report/node-soap/lib/http.js.html +416 -0
  16. package/coverage/lcov-report/node-soap/lib/index.html +171 -0
  17. package/coverage/lcov-report/node-soap/lib/nscontext.js.html +734 -0
  18. package/coverage/lcov-report/node-soap/lib/security/BasicAuthSecurity.js.html +137 -0
  19. package/coverage/lcov-report/node-soap/lib/security/BearerSecurity.js.html +134 -0
  20. package/coverage/lcov-report/node-soap/lib/security/ClientSSLSecurity.js.html +296 -0
  21. package/coverage/lcov-report/node-soap/lib/security/ClientSSLSecurityPFX.js.html +218 -0
  22. package/coverage/lcov-report/node-soap/lib/security/WSSecurity.js.html +278 -0
  23. package/coverage/lcov-report/node-soap/lib/security/index.html +158 -0
  24. package/coverage/lcov-report/node-soap/lib/security/index.js.html +92 -0
  25. package/coverage/lcov-report/node-soap/lib/server.js.html +1139 -0
  26. package/coverage/lcov-report/node-soap/lib/soap.js.html +314 -0
  27. package/coverage/lcov-report/node-soap/lib/utils.js.html +161 -0
  28. package/coverage/lcov-report/node-soap/lib/wsdl.js.html +6275 -0
  29. package/coverage/lcov-report/prettify.css +1 -0
  30. package/coverage/lcov-report/prettify.js +1 -0
  31. package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
  32. package/coverage/lcov-report/sorter.js +158 -0
  33. package/coverage/lcov.info +3325 -0
  34. package/index.js +3 -3
  35. package/lib/client.js +434 -425
  36. package/lib/http.js +129 -129
  37. package/lib/nscontext.js +223 -223
  38. package/lib/security/BasicAuthSecurity.js +24 -24
  39. package/lib/security/BearerSecurity.js +23 -23
  40. package/lib/security/ClientSSLSecurity.js +82 -65
  41. package/lib/security/ClientSSLSecurityPFX.js +51 -51
  42. package/lib/security/WSSecurity.js +90 -90
  43. package/lib/security/WSSecurityCert.js +78 -78
  44. package/lib/security/index.js +10 -10
  45. package/lib/security/templates/wsse-security-header.ejs +12 -12
  46. package/lib/security/templates/wsse-security-token.ejs +3 -3
  47. package/lib/server.js +474 -444
  48. package/lib/soap.d.ts +220 -0
  49. package/lib/soap.js +110 -110
  50. package/lib/utils.js +30 -30
  51. package/lib/wsdl.js +2272 -2234
  52. package/package.json +8 -8
  53. package/soap-stub.js +148 -148
  54. package/.npmignore +0 -2
package/lib/wsdl.js CHANGED
@@ -1,2234 +1,2272 @@
1
- /*
2
- * Copyright (c) 2011 Vinay Pulim <vinay@milewise.com>
3
- * MIT Licensed
4
- *
5
- */
6
- /*jshint proto:true*/
7
-
8
- "use strict";
9
-
10
- var sax = require('sax');
11
- var inherits = require('util').inherits;
12
- var HttpClient = require('./http');
13
- var NamespaceContext = require('./nscontext');
14
- var fs = require('fs');
15
- var url = require('url');
16
- var path = require('path');
17
- var assert = require('assert').ok;
18
- var stripBom = require('strip-bom');
19
- var debug = require('debug')('node-soap');
20
- var _ = require('lodash');
21
- var selectn = require('selectn');
22
- var utils = require('./utils');
23
- var TNS_PREFIX = utils.TNS_PREFIX;
24
- var findPrefix = utils.findPrefix;
25
-
26
- var Primitives = {
27
- string: 1,
28
- boolean: 1,
29
- decimal: 1,
30
- float: 1,
31
- double: 1,
32
- anyType: 1,
33
- byte: 1,
34
- int: 1,
35
- long: 1,
36
- short: 1,
37
- negativeInteger: 1,
38
- nonNegativeInteger: 1,
39
- positiveInteger: 1,
40
- nonPositiveInteger:1,
41
- unsignedByte: 1,
42
- unsignedInt: 1,
43
- unsignedLong: 1,
44
- unsignedShort: 1,
45
- duration: 0,
46
- dateTime: 0,
47
- time: 0,
48
- date: 0,
49
- gYearMonth: 0,
50
- gYear: 0,
51
- gMonthDay: 0,
52
- gDay: 0,
53
- gMonth: 0,
54
- hexBinary: 0,
55
- base64Binary: 0,
56
- anyURI: 0,
57
- QName: 0,
58
- NOTATION: 0
59
- };
60
-
61
- function splitQName(nsName) {
62
- var i = typeof nsName === 'string' ? nsName.indexOf(':') : -1;
63
- return i < 0 ? {prefix: TNS_PREFIX, name: nsName} :
64
- {prefix: nsName.substring(0, i), name: nsName.substring(i + 1)};
65
- }
66
-
67
- function xmlEscape(obj) {
68
- if (typeof (obj) === 'string') {
69
- if (obj.substr(0,9) === '<![CDATA[' && obj.substr(-3) === "]]>") {
70
- return obj;
71
- }
72
- return obj
73
- .replace(/&/g, '&amp;')
74
- .replace(/</g, '&lt;')
75
- .replace(/>/g, '&gt;')
76
- .replace(/"/g, '&quot;')
77
- .replace(/'/g, '&apos;');
78
- }
79
-
80
- return obj;
81
- }
82
-
83
- var trimLeft = /^[\s\xA0]+/;
84
- var trimRight = /[\s\xA0]+$/;
85
-
86
- function trim(text) {
87
- return text.replace(trimLeft, '').replace(trimRight, '');
88
- }
89
-
90
- function deepMerge(destination, source) {
91
- return _.merge(destination || {}, source, function(a, b) {
92
- return _.isArray(a) ? a.concat(b) : undefined;
93
- });
94
- }
95
-
96
- var Element = function(nsName, attrs, options) {
97
- var parts = splitQName(nsName);
98
-
99
- this.nsName = nsName;
100
- this.prefix = parts.prefix;
101
- this.name = parts.name;
102
- this.children = [];
103
- this.xmlns = {};
104
-
105
- this._initializeOptions(options);
106
-
107
- for (var key in attrs) {
108
- var match = /^xmlns:?(.*)$/.exec(key);
109
- if (match) {
110
- this.xmlns[match[1] ? match[1] : TNS_PREFIX] = attrs[key];
111
- }
112
- else {
113
- if(key === 'value') {
114
- this[this.valueKey] = attrs[key];
115
- } else {
116
- this['$' + key] = attrs[key];
117
- }
118
- }
119
- }
120
- if (this.$targetNamespace !== undefined) {
121
- // Add targetNamespace to the mapping
122
- this.xmlns[TNS_PREFIX] = this.$targetNamespace;
123
- }
124
- };
125
-
126
- Element.prototype._initializeOptions = function (options) {
127
- if(options) {
128
- this.valueKey = options.valueKey || '$value';
129
- this.xmlKey = options.xmlKey || '$xml';
130
- this.ignoredNamespaces = options.ignoredNamespaces || [];
131
- } else {
132
- this.valueKey = '$value';
133
- this.xmlKey = '$xml';
134
- this.ignoredNamespaces = [];
135
- }
136
- };
137
-
138
- Element.prototype.deleteFixedAttrs = function() {
139
- this.children && this.children.length === 0 && delete this.children;
140
- this.xmlns && Object.keys(this.xmlns).length === 0 && delete this.xmlns;
141
- delete this.nsName;
142
- delete this.prefix;
143
- delete this.name;
144
- };
145
-
146
- Element.prototype.allowedChildren = [];
147
-
148
- Element.prototype.startElement = function(stack, nsName, attrs, options) {
149
- if (!this.allowedChildren) {
150
- return;
151
- }
152
-
153
- var ChildClass = this.allowedChildren[splitQName(nsName).name],
154
- element = null;
155
-
156
- if (ChildClass) {
157
- stack.push(new ChildClass(nsName, attrs, options));
158
- }
159
- else {
160
- this.unexpected(nsName);
161
- }
162
-
163
- };
164
-
165
- Element.prototype.endElement = function(stack, nsName) {
166
- if (this.nsName === nsName) {
167
- if (stack.length < 2)
168
- return;
169
- var parent = stack[stack.length - 2];
170
- if (this !== stack[0]) {
171
- _.defaultsDeep(stack[0].xmlns, this.xmlns);
172
- // delete this.xmlns;
173
- parent.children.push(this);
174
- parent.addChild(this);
175
- }
176
- stack.pop();
177
- }
178
- };
179
-
180
- Element.prototype.addChild = function(child) {
181
- return;
182
- };
183
-
184
- Element.prototype.unexpected = function(name) {
185
- throw new Error('Found unexpected element (' + name + ') inside ' + this.nsName);
186
- };
187
-
188
- Element.prototype.description = function(definitions) {
189
- return this.$name || this.name;
190
- };
191
-
192
- Element.prototype.init = function() {
193
- };
194
-
195
- Element.createSubClass = function() {
196
- var root = this;
197
- var subElement = function() {
198
- root.apply(this, arguments);
199
- this.init();
200
- };
201
- // inherits(subElement, root);
202
- subElement.prototype.__proto__ = root.prototype;
203
- return subElement;
204
- };
205
-
206
-
207
- var ElementElement = Element.createSubClass();
208
- var AnyElement = Element.createSubClass();
209
- var InputElement = Element.createSubClass();
210
- var OutputElement = Element.createSubClass();
211
- var SimpleTypeElement = Element.createSubClass();
212
- var RestrictionElement = Element.createSubClass();
213
- var ExtensionElement = Element.createSubClass();
214
- var ChoiceElement = Element.createSubClass();
215
- var EnumerationElement = Element.createSubClass();
216
- var ComplexTypeElement = Element.createSubClass();
217
- var ComplexContentElement = Element.createSubClass();
218
- var SimpleContentElement = Element.createSubClass();
219
- var SequenceElement = Element.createSubClass();
220
- var AllElement = Element.createSubClass();
221
- var MessageElement = Element.createSubClass();
222
- var DocumentationElement = Element.createSubClass();
223
-
224
- var SchemaElement = Element.createSubClass();
225
- var TypesElement = Element.createSubClass();
226
- var OperationElement = Element.createSubClass();
227
- var PortTypeElement = Element.createSubClass();
228
- var BindingElement = Element.createSubClass();
229
- var PortElement = Element.createSubClass();
230
- var ServiceElement = Element.createSubClass();
231
- var DefinitionsElement = Element.createSubClass();
232
-
233
- var ElementTypeMap = {
234
- types: [TypesElement, 'schema documentation'],
235
- schema: [SchemaElement, 'element complexType simpleType include import'],
236
- element: [ElementElement, 'annotation complexType'],
237
- any: [AnyElement, ''],
238
- simpleType: [SimpleTypeElement, 'restriction'],
239
- restriction: [RestrictionElement, 'enumeration all choice sequence'],
240
- extension: [ExtensionElement, 'all sequence choice'],
241
- choice: [ChoiceElement, 'element sequence choice any'],
242
- // group: [GroupElement, 'element group'],
243
- enumeration: [EnumerationElement, ''],
244
- complexType: [ComplexTypeElement, 'annotation sequence all complexContent simpleContent choice'],
245
- complexContent: [ComplexContentElement, 'extension'],
246
- simpleContent: [SimpleContentElement, 'extension'],
247
- sequence: [SequenceElement, 'element sequence choice any'],
248
- all: [AllElement, 'element choice'],
249
-
250
- service: [ServiceElement, 'port documentation'],
251
- port: [PortElement, 'address documentation'],
252
- binding: [BindingElement, '_binding SecuritySpec operation documentation'],
253
- portType: [PortTypeElement, 'operation documentation'],
254
- message: [MessageElement, 'part documentation'],
255
- operation: [OperationElement, 'documentation input output fault _operation'],
256
- input: [InputElement, 'body SecuritySpecRef documentation header'],
257
- output: [OutputElement, 'body SecuritySpecRef documentation header'],
258
- fault: [Element, '_fault documentation'],
259
- definitions: [DefinitionsElement, 'types message portType binding service import documentation'],
260
- documentation: [DocumentationElement, '']
261
- };
262
-
263
- function mapElementTypes(types) {
264
- var rtn = {};
265
- types = types.split(' ');
266
- types.forEach(function(type) {
267
- rtn[type.replace(/^_/, '')] = (ElementTypeMap[type] || [Element]) [0];
268
- });
269
- return rtn;
270
- }
271
-
272
- for (var n in ElementTypeMap) {
273
- var v = ElementTypeMap[n];
274
- v[0].prototype.allowedChildren = mapElementTypes(v[1]);
275
- }
276
-
277
- MessageElement.prototype.init = function() {
278
- this.element = null;
279
- this.parts = null;
280
- };
281
-
282
- SchemaElement.prototype.init = function() {
283
- this.complexTypes = {};
284
- this.types = {};
285
- this.elements = {};
286
- this.includes = [];
287
- };
288
-
289
- TypesElement.prototype.init = function() {
290
- this.schemas = {};
291
- };
292
-
293
- OperationElement.prototype.init = function() {
294
- this.input = null;
295
- this.output = null;
296
- this.inputSoap = null;
297
- this.outputSoap = null;
298
- this.style = '';
299
- this.soapAction = '';
300
- };
301
-
302
- PortTypeElement.prototype.init = function() {
303
- this.methods = {};
304
- };
305
-
306
- BindingElement.prototype.init = function() {
307
- this.transport = '';
308
- this.style = '';
309
- this.methods = {};
310
- };
311
-
312
- PortElement.prototype.init = function() {
313
- this.location = null;
314
- };
315
-
316
- ServiceElement.prototype.init = function() {
317
- this.ports = {};
318
- };
319
-
320
- DefinitionsElement.prototype.init = function() {
321
- if (this.name !== 'definitions')this.unexpected(this.nsName);
322
- this.messages = {};
323
- this.portTypes = {};
324
- this.bindings = {};
325
- this.services = {};
326
- this.schemas = {};
327
- };
328
-
329
- DocumentationElement.prototype.init = function() {
330
- };
331
-
332
- SchemaElement.prototype.merge = function(source) {
333
- assert(source instanceof SchemaElement);
334
- if (this.$targetNamespace === source.$targetNamespace) {
335
- _.merge(this.complexTypes, source.complexTypes);
336
- _.merge(this.types, source.types);
337
- _.merge(this.elements, source.elements);
338
- _.merge(this.xmlns, source.xmlns);
339
- }
340
- return this;
341
- };
342
-
343
-
344
- SchemaElement.prototype.addChild = function(child) {
345
- if (child.$name in Primitives)
346
- return;
347
- if (child.name === 'include' || child.name === 'import') {
348
- var location = child.$schemaLocation || child.$location;
349
- if (location) {
350
- this.includes.push({
351
- namespace: child.$namespace || child.$targetNamespace || this.$targetNamespace,
352
- location: location
353
- });
354
- }
355
- }
356
- else if (child.name === 'complexType') {
357
- this.complexTypes[child.$name] = child;
358
- }
359
- else if (child.name === 'element') {
360
- this.elements[child.$name] = child;
361
- }
362
- else if (child.$name) {
363
- this.types[child.$name] = child;
364
- }
365
- this.children.pop();
366
- // child.deleteFixedAttrs();
367
- };
368
- //fix#325
369
- TypesElement.prototype.addChild = function (child) {
370
- assert(child instanceof SchemaElement);
371
-
372
- var targetNamespace = child.$targetNamespace;
373
-
374
- if(!this.schemas.hasOwnProperty(targetNamespace)) {
375
- this.schemas[targetNamespace] = child;
376
- } else {
377
- console.error('Target-Namespace "'+ targetNamespace +'" already in use by another Schema!');
378
- }
379
- };
380
-
381
- InputElement.prototype.addChild = function(child) {
382
- if (child.name === 'body') {
383
- this.use = child.$use;
384
- if (this.use === 'encoded') {
385
- this.encodingStyle = child.$encodingStyle;
386
- }
387
- this.children.pop();
388
- }
389
- };
390
-
391
- OutputElement.prototype.addChild = function(child) {
392
- if (child.name === 'body') {
393
- this.use = child.$use;
394
- if (this.use === 'encoded') {
395
- this.encodingStyle = child.$encodingStyle;
396
- }
397
- this.children.pop();
398
- }
399
- };
400
-
401
- OperationElement.prototype.addChild = function(child) {
402
- if (child.name === 'operation') {
403
- this.soapAction = child.$soapAction || '';
404
- this.style = child.$style || '';
405
- this.children.pop();
406
- }
407
- };
408
-
409
- BindingElement.prototype.addChild = function(child) {
410
- if (child.name === 'binding') {
411
- this.transport = child.$transport;
412
- this.style = child.$style;
413
- this.children.pop();
414
- }
415
- };
416
-
417
- PortElement.prototype.addChild = function(child) {
418
- if (child.name === 'address' && typeof (child.$location) !== 'undefined') {
419
- this.location = child.$location;
420
- }
421
- };
422
-
423
- DefinitionsElement.prototype.addChild = function(child) {
424
- var self = this;
425
- if (child instanceof TypesElement) {
426
- // Merge types.schemas into definitions.schemas
427
- _.merge(self.schemas, child.schemas);
428
- }
429
- else if (child instanceof MessageElement) {
430
- self.messages[child.$name] = child;
431
- }
432
- else if (child.name === 'import') {
433
- self.schemas[child.$namespace] = new SchemaElement(child.$namespace, {});
434
- self.schemas[child.$namespace].addChild(child);
435
- }
436
- else if (child instanceof PortTypeElement) {
437
- self.portTypes[child.$name] = child;
438
- }
439
- else if (child instanceof BindingElement) {
440
- if (child.transport === 'http://schemas.xmlsoap.org/soap/http' ||
441
- child.transport === 'http://www.w3.org/2003/05/soap/bindings/HTTP/')
442
- self.bindings[child.$name] = child;
443
- }
444
- else if (child instanceof ServiceElement) {
445
- self.services[child.$name] = child;
446
- }
447
- else if (child instanceof DocumentationElement) {
448
- }
449
- this.children.pop();
450
- };
451
-
452
- MessageElement.prototype.postProcess = function(definitions) {
453
- var part = null;
454
- var child;
455
- var children = this.children || [];
456
- var ns;
457
- var nsName;
458
- var i;
459
- var type;
460
-
461
- for (i in children) {
462
- if ((child = children[i]).name === 'part') {
463
- part = child;
464
- break;
465
- }
466
- }
467
-
468
- if (!part) {
469
- return;
470
- }
471
-
472
- if (part.$element) {
473
- var lookupTypes = [],
474
- elementChildren ;
475
-
476
- delete this.parts;
477
-
478
- nsName = splitQName(part.$element);
479
- ns = nsName.prefix;
480
- var schema = definitions.schemas[definitions.xmlns[ns]];
481
- this.element = schema.elements[nsName.name];
482
- if(!this.element) {
483
- debug(nsName.name + " is not present in wsdl and cannot be processed correctly.");
484
- return;
485
- }
486
- this.element.targetNSAlias = ns;
487
- this.element.targetNamespace = definitions.xmlns[ns];
488
-
489
- // set the optional $lookupType to be used within `client#_invoke()` when
490
- // calling `wsdl#objectToDocumentXML()
491
- this.element.$lookupType = part.$element;
492
-
493
- elementChildren = this.element.children;
494
-
495
- // get all nested lookup types (only complex types are followed)
496
- if (elementChildren.length > 0) {
497
- for (i = 0; i < elementChildren.length; i++) {
498
- lookupTypes.push(this._getNestedLookupTypeString(elementChildren[i]));
499
- }
500
- }
501
-
502
- // if nested lookup types where found, prepare them for furter usage
503
- if (lookupTypes.length > 0) {
504
- lookupTypes = lookupTypes.
505
- join('_').
506
- split('_').
507
- filter(function removeEmptyLookupTypes (type) {
508
- return type !== '^';
509
- });
510
-
511
- var schemaXmlns = definitions.schemas[this.element.targetNamespace].xmlns;
512
-
513
- for (i = 0; i < lookupTypes.length; i++) {
514
- lookupTypes[i] = this._createLookupTypeObject(lookupTypes[i], schemaXmlns);
515
- }
516
- }
517
-
518
- this.element.$lookupTypes = lookupTypes;
519
-
520
- if (this.element.$type) {
521
- type = splitQName(this.element.$type);
522
- var typeNs = schema.xmlns && schema.xmlns[type.prefix] || definitions.xmlns[type.prefix];
523
-
524
- if (typeNs) {
525
- if (type.name in Primitives) {
526
- // this.element = this.element.$type;
527
- }
528
- else {
529
- // first check local mapping of ns alias to namespace
530
- schema = definitions.schemas[typeNs];
531
- var ctype = schema.complexTypes[type.name] || schema.types[type.name] || schema.elements[type.name];
532
-
533
-
534
- if (ctype) {
535
- this.parts = ctype.description(definitions, schema.xmlns);
536
- }
537
- }
538
- }
539
- }
540
- else {
541
- var method = this.element.description(definitions, schema.xmlns);
542
- this.parts = method[nsName.name];
543
- }
544
-
545
-
546
- this.children.splice(0, 1);
547
- } else {
548
- // rpc encoding
549
- this.parts = {};
550
- delete this.element;
551
- for (i = 0; part = this.children[i]; i++) {
552
- if (part.name === 'documentation') {
553
- // <wsdl:documentation can be present under <wsdl:message>
554
- continue;
555
- }
556
- assert(part.name === 'part', 'Expected part element');
557
- nsName = splitQName(part.$type);
558
- ns = definitions.xmlns[nsName.prefix];
559
- type = nsName.name;
560
- var schemaDefinition = definitions.schemas[ns];
561
- if (typeof schemaDefinition !== 'undefined') {
562
- this.parts[part.$name] = definitions.schemas[ns].types[type] || definitions.schemas[ns].complexTypes[type];
563
- } else {
564
- this.parts[part.$name] = part.$type;
565
- }
566
-
567
- if (typeof this.parts[part.$name] === 'object') {
568
- this.parts[part.$name].prefix = nsName.prefix;
569
- this.parts[part.$name].xmlns = ns;
570
- }
571
-
572
- this.children.splice(i--, 1);
573
- }
574
- }
575
- this.deleteFixedAttrs();
576
- };
577
-
578
- /**
579
- * Takes a given namespaced String(for example: 'alias:property') and creates a lookupType
580
- * object for further use in as first (lookup) `parameterTypeObj` within the `objectToXML`
581
- * method and provides an entry point for the already existing code in `findChildSchemaObject`.
582
- *
583
- * @method _createLookupTypeObject
584
- * @param {String} nsString The NS String (for example "alias:type").
585
- * @param {Object} xmlns The fully parsed `wsdl` definitions object (including all schemas).
586
- * @returns {Object}
587
- * @private
588
- */
589
- MessageElement.prototype._createLookupTypeObject = function (nsString, xmlns) {
590
- var splittedNSString = splitQName(nsString),
591
- nsAlias = splittedNSString.prefix,
592
- splittedName = splittedNSString.name.split('#'),
593
- type = splittedName[0],
594
- name = splittedName[1],
595
- lookupTypeObj = {};
596
-
597
- lookupTypeObj.$namespace = xmlns[nsAlias];
598
- lookupTypeObj.$type = nsAlias + ':' + type;
599
- lookupTypeObj.$name = name;
600
-
601
- return lookupTypeObj;
602
- };
603
-
604
- /**
605
- * Iterates through the element and every nested child to find any defined `$type`
606
- * property and returns it in a underscore ('_') separated String (using '^' as default
607
- * value if no `$type` property was found).
608
- *
609
- * @method _getNestedLookupTypeString
610
- * @param {Object} element The element which (probably) contains nested `$type` values.
611
- * @returns {String}
612
- * @private
613
- */
614
- MessageElement.prototype._getNestedLookupTypeString = function (element) {
615
- var resolvedType = '^',
616
- excluded = this.ignoredNamespaces.concat('xs'); // do not process $type values wich start with
617
-
618
- if (element.hasOwnProperty('$type') && typeof element.$type === 'string') {
619
- if (excluded.indexOf(element.$type.split(':')[0]) === -1) {
620
- resolvedType += ('_' + element.$type + '#' + element.$name);
621
- }
622
- }
623
-
624
- if (element.children.length > 0) {
625
- var self = this;
626
-
627
- element.children.forEach(function (child) {
628
- var resolvedChildType = self._getNestedLookupTypeString(child).replace(/\^_/, '');
629
-
630
- if (resolvedChildType && typeof resolvedChildType === 'string') {
631
- resolvedType += ('_' + resolvedChildType);
632
- }
633
- });
634
- }
635
-
636
- return resolvedType;
637
- };
638
-
639
- OperationElement.prototype.postProcess = function(definitions, tag) {
640
- var children = this.children;
641
- for (var i = 0, child; child = children[i]; i++) {
642
- if (child.name !== 'input' && child.name !== 'output')
643
- continue;
644
- if (tag === 'binding') {
645
- this[child.name] = child;
646
- children.splice(i--, 1);
647
- continue;
648
- }
649
- var messageName = splitQName(child.$message).name;
650
- var message = definitions.messages[messageName];
651
- message.postProcess(definitions);
652
- if (message.element) {
653
- definitions.messages[message.element.$name] = message;
654
- this[child.name] = message.element;
655
- }
656
- else {
657
- this[child.name] = message;
658
- }
659
- children.splice(i--, 1);
660
- }
661
- this.deleteFixedAttrs();
662
- };
663
-
664
- PortTypeElement.prototype.postProcess = function(definitions) {
665
- var children = this.children;
666
- if (typeof children === 'undefined')
667
- return;
668
- for (var i = 0, child; child = children[i]; i++) {
669
- if (child.name !== 'operation')
670
- continue;
671
- child.postProcess(definitions, 'portType');
672
- this.methods[child.$name] = child;
673
- children.splice(i--, 1);
674
- }
675
- delete this.$name;
676
- this.deleteFixedAttrs();
677
- };
678
-
679
- BindingElement.prototype.postProcess = function(definitions) {
680
- var type = splitQName(this.$type).name,
681
- portType = definitions.portTypes[type],
682
- style = this.style,
683
- children = this.children;
684
- if (portType){
685
- portType.postProcess(definitions);
686
- this.methods = portType.methods;
687
-
688
- for (var i = 0, child; child = children[i]; i++) {
689
- if (child.name !== 'operation')
690
- continue;
691
- child.postProcess(definitions, 'binding');
692
- children.splice(i--, 1);
693
- child.style || (child.style = style);
694
- var method = this.methods[child.$name];
695
-
696
- if (method) {
697
- method.style = child.style;
698
- method.soapAction = child.soapAction;
699
- method.inputSoap = child.input || null;
700
- method.outputSoap = child.output || null;
701
- method.inputSoap && method.inputSoap.deleteFixedAttrs();
702
- method.outputSoap && method.outputSoap.deleteFixedAttrs();
703
- }
704
- }
705
- }
706
- delete this.$name;
707
- delete this.$type;
708
- this.deleteFixedAttrs();
709
- };
710
-
711
- ServiceElement.prototype.postProcess = function(definitions) {
712
- var children = this.children,
713
- bindings = definitions.bindings;
714
- if (children && children.length > 0) {
715
- for (var i = 0, child; child = children[i]; i++) {
716
- if (child.name !== 'port')
717
- continue;
718
- var bindingName = splitQName(child.$binding).name;
719
- var binding = bindings[bindingName];
720
- if (binding) {
721
- binding.postProcess(definitions);
722
- this.ports[child.$name] = {
723
- location: child.location,
724
- binding: binding
725
- };
726
- children.splice(i--, 1);
727
- }
728
- }
729
- }
730
- delete this.$name;
731
- this.deleteFixedAttrs();
732
- };
733
-
734
-
735
- SimpleTypeElement.prototype.description = function(definitions) {
736
- var children = this.children;
737
- for (var i = 0, child; child = children[i]; i++) {
738
- if (child instanceof RestrictionElement)
739
- return this.$name + "|" + child.description();
740
- }
741
- return {};
742
- };
743
-
744
- RestrictionElement.prototype.description = function(definitions, xmlns) {
745
- var children = this.children;
746
- var desc;
747
- for (var i=0, child; child=children[i]; i++) {
748
- if (child instanceof SequenceElement ||
749
- child instanceof ChoiceElement) {
750
- desc = child.description(definitions, xmlns);
751
- break;
752
- }
753
- }
754
- if (desc && this.$base) {
755
- var type = splitQName(this.$base),
756
- typeName = type.name,
757
- ns = xmlns && xmlns[type.prefix] || definitions.xmlns[type.prefix],
758
- schema = definitions.schemas[ns],
759
- typeElement = schema && ( schema.complexTypes[typeName] || schema.types[typeName] || schema.elements[typeName] );
760
-
761
- desc.getBase = function() {
762
- return typeElement.description(definitions, schema.xmlns);
763
- };
764
- return desc;
765
- }
766
-
767
- // then simple element
768
- var base = this.$base ? this.$base + "|" : "";
769
- return base + this.children.map(function(child) {
770
- return child.description();
771
- }).join(",");
772
- };
773
-
774
- ExtensionElement.prototype.description = function(definitions, xmlns) {
775
- var children = this.children;
776
- var desc = {};
777
- for (var i=0, child; child=children[i]; i++) {
778
- if (child instanceof SequenceElement ||
779
- child instanceof ChoiceElement) {
780
- desc = child.description(definitions, xmlns);
781
- }
782
- }
783
- if (this.$base) {
784
- var type = splitQName(this.$base),
785
- typeName = type.name,
786
- ns = xmlns && xmlns[type.prefix] || definitions.xmlns[type.prefix],
787
- schema = definitions.schemas[ns];
788
-
789
- if (typeName in Primitives) {
790
- return this.$base;
791
- }
792
- else {
793
- var typeElement = schema && ( schema.complexTypes[typeName] ||
794
- schema.types[typeName] || schema.elements[typeName] );
795
-
796
- if (typeElement) {
797
- var base = typeElement.description(definitions, schema.xmlns);
798
- desc = _.defaultsDeep(base, desc);
799
- }
800
- }
801
- }
802
- return desc;
803
- };
804
-
805
- EnumerationElement.prototype.description = function() {
806
- return this[this.valueKey];
807
- };
808
-
809
- ComplexTypeElement.prototype.description = function(definitions, xmlns) {
810
- var children = this.children || [];
811
- for (var i=0, child; child=children[i]; i++) {
812
- if (child instanceof ChoiceElement ||
813
- child instanceof SequenceElement ||
814
- child instanceof AllElement ||
815
- child instanceof SimpleContentElement ||
816
- child instanceof ComplexContentElement) {
817
-
818
- return child.description(definitions, xmlns);
819
- }
820
- }
821
- return {};
822
- };
823
-
824
- ComplexContentElement.prototype.description = function(definitions, xmlns) {
825
- var children = this.children;
826
- for (var i = 0, child; child = children[i]; i++) {
827
- if (child instanceof ExtensionElement) {
828
- return child.description(definitions, xmlns);
829
- }
830
- }
831
- return {};
832
- };
833
-
834
- SimpleContentElement.prototype.description = function(definitions, xmlns) {
835
- var children = this.children;
836
- for (var i = 0, child; child = children[i]; i++) {
837
- if (child instanceof ExtensionElement) {
838
- return child.description(definitions, xmlns);
839
- }
840
- }
841
- return {};
842
- };
843
-
844
- ElementElement.prototype.description = function(definitions, xmlns) {
845
- var element = {},
846
- name = this.$name;
847
- var isMany = !this.$maxOccurs ? false : (isNaN(this.$maxOccurs) ? (this.$maxOccurs === 'unbounded') : (this.$maxOccurs > 1));
848
- if (this.$minOccurs !== this.$maxOccurs && isMany) {
849
- name += '[]';
850
- }
851
-
852
- if (xmlns && xmlns[TNS_PREFIX]) {
853
- this.$targetNamespace = xmlns[TNS_PREFIX];
854
- }
855
- var type = this.$type || this.$ref;
856
- if (type) {
857
- type = splitQName(type);
858
- var typeName = type.name,
859
- ns = xmlns && xmlns[type.prefix] || definitions.xmlns[type.prefix],
860
- schema = definitions.schemas[ns],
861
- typeElement = schema && ( this.$type? schema.complexTypes[typeName] || schema.types[typeName] : schema.elements[typeName] );
862
-
863
- if (ns && definitions.schemas[ns]) {
864
- xmlns = definitions.schemas[ns].xmlns;
865
- }
866
-
867
- if (typeElement && !(typeName in Primitives)) {
868
-
869
- if (!(typeName in definitions.descriptions.types)) {
870
-
871
- var elem = {};
872
- definitions.descriptions.types[typeName] = elem;
873
- var description = typeElement.description(definitions, xmlns);
874
- if (typeof description === 'string') {
875
- elem = description;
876
- }
877
- else {
878
- Object.keys(description).forEach(function (key) {
879
- elem[key] = description[key];
880
- });
881
- }
882
-
883
- if (this.$ref) {
884
- element = elem;
885
- }
886
- else {
887
- element[name] = elem;
888
- }
889
-
890
- if (typeof elem === 'object') {
891
- elem.targetNSAlias = type.prefix;
892
- elem.targetNamespace = ns;
893
- }
894
-
895
- definitions.descriptions.types[typeName] = elem;
896
- }
897
- else {
898
- if (this.$ref) {
899
- element = definitions.descriptions.types[typeName];
900
- }
901
- else {
902
- element[name] = definitions.descriptions.types[typeName];
903
- }
904
- }
905
-
906
- }
907
- else {
908
- element[name] = this.$type;
909
- }
910
- }
911
- else {
912
- var children = this.children;
913
- element[name] = {};
914
- for (var i = 0, child; child = children[i]; i++) {
915
- if (child instanceof ComplexTypeElement) {
916
- element[name] = child.description(definitions, xmlns);
917
- }
918
- }
919
- }
920
- return element;
921
- };
922
-
923
- AllElement.prototype.description =
924
- SequenceElement.prototype.description = function(definitions, xmlns) {
925
- var children = this.children;
926
- var sequence = {};
927
- for (var i = 0, child; child = children[i]; i++) {
928
- if (child instanceof AnyElement) {
929
- continue;
930
- }
931
- var description = child.description(definitions, xmlns);
932
- for (var key in description) {
933
- sequence[key] = description[key];
934
- }
935
- }
936
- return sequence;
937
- };
938
-
939
- ChoiceElement.prototype.description = function(definitions, xmlns) {
940
- var children = this.children;
941
- var choice = {};
942
- for (var i=0, child; child=children[i]; i++) {
943
- var description = child.description(definitions, xmlns);
944
- for (var key in description) {
945
- choice[key] = description[key];
946
- }
947
- }
948
- return choice;
949
- };
950
-
951
- MessageElement.prototype.description = function(definitions) {
952
- if (this.element) {
953
- return this.element && this.element.description(definitions);
954
- }
955
- var desc = {};
956
- desc[this.$name] = this.parts;
957
- return desc;
958
- };
959
-
960
- PortTypeElement.prototype.description = function(definitions) {
961
- var methods = {};
962
- for (var name in this.methods) {
963
- var method = this.methods[name];
964
- methods[name] = method.description(definitions);
965
- }
966
- return methods;
967
- };
968
-
969
- OperationElement.prototype.description = function(definitions) {
970
- var inputDesc = this.input ? this.input.description(definitions) : null;
971
- var outputDesc = this.output ? this.output.description(definitions) : null;
972
- return {
973
- input: inputDesc && inputDesc[Object.keys(inputDesc)[0]],
974
- output: outputDesc && outputDesc[Object.keys(outputDesc)[0]]
975
- };
976
- };
977
-
978
- BindingElement.prototype.description = function(definitions) {
979
- var methods = {};
980
- for (var name in this.methods) {
981
- var method = this.methods[name];
982
- methods[name] = method.description(definitions);
983
- }
984
- return methods;
985
- };
986
-
987
- ServiceElement.prototype.description = function(definitions) {
988
- var ports = {};
989
- for (var name in this.ports) {
990
- var port = this.ports[name];
991
- ports[name] = port.binding.description(definitions);
992
- }
993
- return ports;
994
- };
995
-
996
- var WSDL = function(definition, uri, options) {
997
- var self = this,
998
- fromFunc;
999
-
1000
- this.uri = uri;
1001
- this.callback = function() {
1002
- };
1003
- this._includesWsdl = [];
1004
-
1005
- // initialize WSDL cache
1006
- this.WSDL_CACHE = (options || {}).WSDL_CACHE || {};
1007
-
1008
- this._initializeOptions(options);
1009
-
1010
- if (typeof definition === 'string') {
1011
- definition = stripBom(definition);
1012
- fromFunc = this._fromXML;
1013
- }
1014
- else if (typeof definition === 'object') {
1015
- fromFunc = this._fromServices;
1016
- }
1017
- else {
1018
- throw new Error('WSDL constructor takes either an XML string or service definition');
1019
- }
1020
-
1021
- process.nextTick(function() {
1022
- try {
1023
- fromFunc.call(self, definition);
1024
- } catch (e) {
1025
- return self.callback(e.message);
1026
- }
1027
-
1028
- self.processIncludes(function(err) {
1029
- var name;
1030
- if (err) {
1031
- return self.callback(err);
1032
- }
1033
-
1034
- self.definitions.deleteFixedAttrs();
1035
- var services = self.services = self.definitions.services;
1036
- if (services) {
1037
- for (name in services) {
1038
- services[name].postProcess(self.definitions);
1039
- }
1040
- }
1041
- var complexTypes = self.definitions.complexTypes;
1042
- if (complexTypes) {
1043
- for (name in complexTypes) {
1044
- complexTypes[name].deleteFixedAttrs();
1045
- }
1046
- }
1047
-
1048
- // for document style, for every binding, prepare input message element name to (methodName, output message element name) mapping
1049
- var bindings = self.definitions.bindings;
1050
- for (var bindingName in bindings) {
1051
- var binding = bindings[bindingName];
1052
- if (typeof binding.style === 'undefined') {
1053
- binding.style = 'document';
1054
- }
1055
- if (binding.style !== 'document')
1056
- continue;
1057
- var methods = binding.methods;
1058
- var topEls = binding.topElements = {};
1059
- for (var methodName in methods) {
1060
- if (methods[methodName].input) {
1061
- var inputName = methods[methodName].input.$name;
1062
- var outputName="";
1063
- if(methods[methodName].output )
1064
- outputName = methods[methodName].output.$name;
1065
- topEls[inputName] = {"methodName": methodName, "outputName": outputName};
1066
- }
1067
- }
1068
- }
1069
-
1070
- // prepare soap envelope xmlns definition string
1071
- self.xmlnsInEnvelope = self._xmlnsMap();
1072
-
1073
- self.callback(err, self);
1074
- });
1075
-
1076
- });
1077
- };
1078
-
1079
- WSDL.prototype.ignoredNamespaces = ['tns', 'targetNamespace', 'typedNamespace'];
1080
-
1081
- WSDL.prototype.ignoreBaseNameSpaces = false;
1082
-
1083
- WSDL.prototype.valueKey = '$value';
1084
- WSDL.prototype.xmlKey = '$xml';
1085
-
1086
- WSDL.prototype._initializeOptions = function (options) {
1087
- this._originalIgnoredNamespaces = (options || {}).ignoredNamespaces;
1088
- this.options = {};
1089
-
1090
- var ignoredNamespaces = options ? options.ignoredNamespaces : null;
1091
-
1092
- if (ignoredNamespaces &&
1093
- (Array.isArray(ignoredNamespaces.namespaces) || typeof ignoredNamespaces.namespaces === 'string')) {
1094
- if (ignoredNamespaces.override) {
1095
- this.options.ignoredNamespaces = ignoredNamespaces.namespaces;
1096
- } else {
1097
- this.options.ignoredNamespaces = this.ignoredNamespaces.concat(ignoredNamespaces.namespaces);
1098
- }
1099
- } else {
1100
- this.options.ignoredNamespaces = this.ignoredNamespaces;
1101
- }
1102
-
1103
- this.options.valueKey = options.valueKey || this.valueKey;
1104
- this.options.xmlKey = options.xmlKey || this.xmlKey;
1105
- if (options.escapeXML !== undefined) {
1106
- this.options.escapeXML = options.escapeXML;
1107
- } else {
1108
- this.options.escapeXML = true;
1109
- }
1110
- if (options.returnFault !== undefined) {
1111
- this.options.returnFault = options.returnFault;
1112
- } else {
1113
- this.options.returnFault = false;
1114
- }
1115
- this.options.handleNilAsNull = !!options.handleNilAsNull;
1116
-
1117
- // Allow any request headers to keep passing through
1118
- this.options.wsdl_headers = options.wsdl_headers;
1119
- this.options.wsdl_options = options.wsdl_options;
1120
- if (options.httpClient) {
1121
- this.options.httpClient = options.httpClient;
1122
- }
1123
-
1124
- // The supplied request-object should be passed through
1125
- if (options.request) {
1126
- this.options.request = options.request;
1127
- }
1128
-
1129
- var ignoreBaseNameSpaces = options ? options.ignoreBaseNameSpaces : null;
1130
- if (ignoreBaseNameSpaces !== null && typeof ignoreBaseNameSpaces !== 'undefined') {
1131
- this.options.ignoreBaseNameSpaces = ignoreBaseNameSpaces;
1132
- } else {
1133
- this.options.ignoreBaseNameSpaces = this.ignoreBaseNameSpaces;
1134
- }
1135
-
1136
- // Works only in client
1137
- this.options.forceSoap12Headers = options.forceSoap12Headers;
1138
- this.options.customDeserializer = options.customDeserializer;
1139
-
1140
- if (options.overrideRootElement !== undefined) {
1141
- this.options.overrideRootElement = options.overrideRootElement;
1142
- }
1143
- };
1144
-
1145
- WSDL.prototype.onReady = function(callback) {
1146
- if (callback)
1147
- this.callback = callback;
1148
- };
1149
-
1150
- WSDL.prototype._processNextInclude = function(includes, callback) {
1151
- var self = this,
1152
- include = includes.shift(),
1153
- options;
1154
-
1155
- if (!include)
1156
- return callback();
1157
-
1158
- var includePath;
1159
- if (!/^https?:/.test(self.uri) && !/^https?:/.test(include.location)) {
1160
- includePath = path.resolve(path.dirname(self.uri), include.location);
1161
- } else {
1162
- includePath = url.resolve(self.uri||'', include.location);
1163
- }
1164
-
1165
- options = _.assign({}, this.options);
1166
- // follow supplied ignoredNamespaces option
1167
- options.ignoredNamespaces = this._originalIgnoredNamespaces || this.options.ignoredNamespaces;
1168
- options.WSDL_CACHE = this.WSDL_CACHE;
1169
-
1170
- open_wsdl_recursive(includePath, options, function(err, wsdl) {
1171
- if (err) {
1172
- return callback(err);
1173
- }
1174
-
1175
- self._includesWsdl.push(wsdl);
1176
-
1177
- if (wsdl.definitions instanceof DefinitionsElement) {
1178
- _.merge(self.definitions, wsdl.definitions, function(a,b) {
1179
- return (a instanceof SchemaElement) ? a.merge(b) : undefined;
1180
- });
1181
- } else {
1182
- self.definitions.schemas[include.namespace || wsdl.definitions.$targetNamespace] = deepMerge(self.definitions.schemas[include.namespace || wsdl.definitions.$targetNamespace], wsdl.definitions);
1183
- }
1184
- self._processNextInclude(includes, function(err) {
1185
- callback(err);
1186
- });
1187
- });
1188
- };
1189
-
1190
- WSDL.prototype.processIncludes = function(callback) {
1191
- var schemas = this.definitions.schemas,
1192
- includes = [];
1193
-
1194
- for (var ns in schemas) {
1195
- var schema = schemas[ns];
1196
- includes = includes.concat(schema.includes || []);
1197
- }
1198
-
1199
- this._processNextInclude(includes, callback);
1200
- };
1201
-
1202
- WSDL.prototype.describeServices = function() {
1203
- var services = {};
1204
- for (var name in this.services) {
1205
- var service = this.services[name];
1206
- services[name] = service.description(this.definitions);
1207
- }
1208
- return services;
1209
- };
1210
-
1211
- WSDL.prototype.toXML = function() {
1212
- return this.xml || '';
1213
- };
1214
-
1215
- WSDL.prototype.xmlToObject = function(xml, callback) {
1216
- var self = this;
1217
- var p = typeof callback === 'function' ? {} : sax.parser(true);
1218
- var objectName = null;
1219
- var root = {};
1220
- var schema = {
1221
- Envelope: {
1222
- Header: {
1223
- Security: {
1224
- UsernameToken: {
1225
- Username: 'string',
1226
- Password: 'string'
1227
- }
1228
- }
1229
- },
1230
- Body: {
1231
- Fault: {
1232
- faultcode: 'string',
1233
- faultstring: 'string',
1234
- detail: 'string'
1235
- }
1236
- }
1237
- }
1238
- };
1239
- var stack = [{name: null, object: root, schema: schema}];
1240
- var xmlns = {};
1241
-
1242
- var refs = {}, id; // {id:{hrefs:[],obj:}, ...}
1243
-
1244
- p.onopentag = function(node) {
1245
- var nsName = node.name;
1246
- var attrs = node.attributes;
1247
-
1248
- var name = splitQName(nsName).name,
1249
- attributeName,
1250
- top = stack[stack.length - 1],
1251
- topSchema = top.schema,
1252
- elementAttributes = {},
1253
- hasNonXmlnsAttribute = false,
1254
- hasNilAttribute = false,
1255
- obj = {};
1256
- var originalName = name;
1257
-
1258
- if (!objectName && top.name === 'Body' && name !== 'Fault') {
1259
- var message = self.definitions.messages[name];
1260
- // Support RPC/literal messages where response body contains one element named
1261
- // after the operation + 'Response'. See http://www.w3.org/TR/wsdl#_names
1262
- if (!message) {
1263
- try {
1264
- // Determine if this is request or response
1265
- var isInput = false;
1266
- var isOutput = false;
1267
- if ((/Response$/).test(name)) {
1268
- isOutput = true;
1269
- name = name.replace(/Response$/, '');
1270
- } else if ((/Request$/).test(name)) {
1271
- isInput = true;
1272
- name = name.replace(/Request$/, '');
1273
- } else if ((/Solicit$/).test(name)) {
1274
- isInput = true;
1275
- name = name.replace(/Solicit$/, '');
1276
- }
1277
- // Look up the appropriate message as given in the portType's operations
1278
- var portTypes = self.definitions.portTypes;
1279
- var portTypeNames = Object.keys(portTypes);
1280
- // Currently this supports only one portType definition.
1281
- var portType = portTypes[portTypeNames[0]];
1282
- if (isInput) {
1283
- name = portType.methods[name].input.$name;
1284
- } else {
1285
- name = portType.methods[name].output.$name;
1286
- }
1287
- message = self.definitions.messages[name];
1288
- // 'cache' this alias to speed future lookups
1289
- self.definitions.messages[originalName] = self.definitions.messages[name];
1290
- } catch (e) {
1291
- if (self.options.returnFault) {
1292
- p.onerror(e);
1293
- }
1294
- }
1295
- }
1296
-
1297
- topSchema = message.description(self.definitions);
1298
- objectName = originalName;
1299
- }
1300
-
1301
- if (attrs.href) {
1302
- id = attrs.href.substr(1);
1303
- if (!refs[id]) {
1304
- refs[id] = {hrefs: [], obj: null};
1305
- }
1306
- refs[id].hrefs.push({par: top.object, key: name, obj: obj});
1307
- }
1308
- if (id = attrs.id) {
1309
- if (!refs[id]) {
1310
- refs[id] = {hrefs: [], obj: null};
1311
- }
1312
- }
1313
-
1314
- //Handle element attributes
1315
- for (attributeName in attrs) {
1316
- if (/^xmlns:|^xmlns$/.test(attributeName)) {
1317
- xmlns[splitQName(attributeName).name] = attrs[attributeName];
1318
- continue;
1319
- }
1320
- hasNonXmlnsAttribute = true;
1321
- elementAttributes[attributeName] = attrs[attributeName];
1322
- }
1323
-
1324
- for(attributeName in elementAttributes){
1325
- var res = splitQName(attributeName);
1326
- if (res.name === 'nil' && xmlns[res.prefix] === 'http://www.w3.org/2001/XMLSchema-instance') {
1327
- hasNilAttribute = true;
1328
- break;
1329
- }
1330
- }
1331
-
1332
- if (hasNonXmlnsAttribute) {
1333
- obj[self.options.attributesKey] = elementAttributes;
1334
- }
1335
-
1336
- // Pick up the schema for the type specified in element's xsi:type attribute.
1337
- var xsiTypeSchema;
1338
- var xsiType = elementAttributes['xsi:type'];
1339
- if (xsiType) {
1340
- var type = splitQName(xsiType);
1341
- var typeURI;
1342
- if (type.prefix === TNS_PREFIX) {
1343
- // In case of xsi:type = "MyType"
1344
- typeURI = xmlns[type.prefix] || xmlns.xmlns;
1345
- } else {
1346
- typeURI = xmlns[type.prefix];
1347
- }
1348
- var typeDef = self.findSchemaObject(typeURI, type.name);
1349
- if (typeDef) {
1350
- xsiTypeSchema = typeDef.description(self.definitions);
1351
- }
1352
- }
1353
-
1354
- if (topSchema && topSchema[name + '[]']) {
1355
- name = name + '[]';
1356
- }
1357
- stack.push({name: originalName, object: obj, schema: (xsiTypeSchema || (topSchema && topSchema[name])), id: attrs.id, nil: hasNilAttribute});
1358
- };
1359
-
1360
- p.onclosetag = function(nsName) {
1361
- var cur = stack.pop(),
1362
- obj = cur.object,
1363
- top = stack[stack.length - 1],
1364
- topObject = top.object,
1365
- topSchema = top.schema,
1366
- name = splitQName(nsName).name;
1367
-
1368
- if (typeof cur.schema === 'string' && (cur.schema === 'string' || cur.schema.split(':')[1] === 'string')) {
1369
- if (typeof obj === 'object' && Object.keys(obj).length === 0) obj = cur.object = '';
1370
- }
1371
-
1372
- if (cur.nil === true) {
1373
- if (self.options.handleNilAsNull) {
1374
- obj = null;
1375
- } else {
1376
- return;
1377
- }
1378
- }
1379
-
1380
- if (_.isPlainObject(obj) && !Object.keys(obj).length) {
1381
- obj = null;
1382
- }
1383
-
1384
- if (topSchema && topSchema[name + '[]']) {
1385
- if (!topObject[name]) {
1386
- topObject[name] = [];
1387
- }
1388
- topObject[name].push(obj);
1389
- } else if (name in topObject) {
1390
- if (!Array.isArray(topObject[name])) {
1391
- topObject[name] = [topObject[name]];
1392
- }
1393
- topObject[name].push(obj);
1394
- } else {
1395
- topObject[name] = obj;
1396
- }
1397
-
1398
- if (cur.id) {
1399
- refs[cur.id].obj = obj;
1400
- }
1401
- };
1402
-
1403
- p.oncdata = function (text) {
1404
- text = trim(text);
1405
- if (!text.length) {
1406
- return;
1407
- }
1408
-
1409
- if (/<\?xml[\s\S]+\?>/.test(text)) {
1410
- var top = stack[stack.length - 1];
1411
- var value = self.xmlToObject(text);
1412
- if (top.object[self.options.attributesKey]) {
1413
- top.object[self.options.valueKey] = value;
1414
- } else {
1415
- top.object = value;
1416
- }
1417
- } else {
1418
- p.ontext(text);
1419
- }
1420
- };
1421
-
1422
- p.onerror = function(e) {
1423
- p.resume();
1424
- throw {
1425
- Fault: {
1426
- faultcode: 500,
1427
- faultstring: 'Invalid XML',
1428
- detail: new Error(e).message,
1429
- statusCode: 500
1430
- }
1431
- };
1432
- };
1433
-
1434
- p.ontext = function(text) {
1435
- text = trim(text);
1436
- if (!text.length) {
1437
- return;
1438
- }
1439
-
1440
- var top = stack[stack.length - 1];
1441
- var name = splitQName(top.schema).name,
1442
- value;
1443
- if (self.options && self.options.customDeserializer && self.options.customDeserializer[name]) {
1444
- value = self.options.customDeserializer[name](text, top);
1445
- }
1446
- else {
1447
- if (name === 'int' || name === 'integer') {
1448
- value = parseInt(text, 10);
1449
- } else if (name === 'bool' || name === 'boolean') {
1450
- value = text.toLowerCase() === 'true' || text === '1';
1451
- } else if (name === 'dateTime' || name === 'date') {
1452
- value = new Date(text);
1453
- } else {
1454
- // handle string or other types
1455
- if (typeof top.object !== 'string') {
1456
- value = text;
1457
- } else {
1458
- value = top.object + text;
1459
- }
1460
- }
1461
- }
1462
-
1463
- if (top.object[self.options.attributesKey]) {
1464
- top.object[self.options.valueKey] = value;
1465
- } else {
1466
- top.object = value;
1467
- }
1468
- };
1469
-
1470
- if (typeof callback === 'function') {
1471
- // we be streaming
1472
- var saxStream = sax.createStream(true);
1473
- saxStream.on('opentag', p.onopentag);
1474
- saxStream.on('closetag', p.onclosetag);
1475
- saxStream.on('cdata', p.oncdata);
1476
- saxStream.on('text', p.ontext);
1477
- xml.pipe(saxStream)
1478
- .on('error', function (err) {
1479
- callback(err);
1480
- })
1481
- .on('end', function () {
1482
- var r;
1483
- try {
1484
- r = finish();
1485
- } catch (e) {
1486
- return callback(e);
1487
- }
1488
- callback(null, r);
1489
- });
1490
- return;
1491
- }
1492
- p.write(xml).close();
1493
-
1494
- return finish();
1495
-
1496
- function finish() {
1497
- // MultiRef support: merge objects instead of replacing
1498
- for (var n in refs) {
1499
- var ref = refs[n];
1500
- for (var i = 0; i < ref.hrefs.length; i++) {
1501
- _.assign(ref.hrefs[i].obj, ref.obj);
1502
- }
1503
- }
1504
-
1505
- if (root.Envelope) {
1506
- var body = root.Envelope.Body;
1507
- if (body && body.Fault) {
1508
- var code = selectn('faultcode.$value', body.Fault) || selectn('faultcode', body.Fault);
1509
- var string = selectn('faultstring.$value', body.Fault) || selectn('faultstring', body.Fault);
1510
- var detail = selectn('detail.$value', body.Fault) || selectn('detail.message', body.Fault);
1511
- var error = new Error(code + ': ' + string + (detail ? ': ' + detail : ''));
1512
- error.root = root;
1513
- throw error;
1514
- }
1515
- return root.Envelope;
1516
- }
1517
- return root;
1518
- }
1519
- };
1520
-
1521
- /**
1522
- * Look up a XSD type or element by namespace URI and name
1523
- * @param {String} nsURI Namespace URI
1524
- * @param {String} qname Local or qualified name
1525
- * @returns {*} The XSD type/element definition
1526
- */
1527
- WSDL.prototype.findSchemaObject = function(nsURI, qname) {
1528
- if (!nsURI || !qname) {
1529
- return null;
1530
- }
1531
-
1532
- var def = null;
1533
-
1534
- if (this.definitions.schemas) {
1535
- var schema = this.definitions.schemas[nsURI];
1536
- if (schema) {
1537
- if (qname.indexOf(':') !== -1) {
1538
- qname = qname.substring(qname.indexOf(':') + 1, qname.length);
1539
- }
1540
-
1541
- // if the client passed an input element which has a `$lookupType` property instead of `$type`
1542
- // the `def` is found in `schema.elements`.
1543
- def = schema.complexTypes[qname] || schema.types[qname] || schema.elements[qname];
1544
- }
1545
- }
1546
-
1547
- return def;
1548
- };
1549
-
1550
- /**
1551
- * Create document style xml string from the parameters
1552
- * @param {String} name
1553
- * @param {*} params
1554
- * @param {String} nsPrefix
1555
- * @param {String} nsURI
1556
- * @param {String} type
1557
- */
1558
- WSDL.prototype.objectToDocumentXML = function(name, params, nsPrefix, nsURI, type) {
1559
- //If user supplies XML already, just use that. XML Declaration should not be present.
1560
- if (params && params._xml) {
1561
- return params._xml;
1562
- }
1563
- var args = {};
1564
- args[name] = params;
1565
- var parameterTypeObj = type ? this.findSchemaObject(nsURI, type) : null;
1566
- return this.objectToXML(args, null, nsPrefix, nsURI, true, null, parameterTypeObj);
1567
- };
1568
-
1569
- /**
1570
- * Create RPC style xml string from the parameters
1571
- * @param {String} name
1572
- * @param {*} params
1573
- * @param {String} nsPrefix
1574
- * @param {String} nsURI
1575
- * @returns {string}
1576
- */
1577
- WSDL.prototype.objectToRpcXML = function(name, params, nsPrefix, nsURI,isParts) {
1578
- var parts = [];
1579
- var defs = this.definitions;
1580
- var nsAttrName = '_xmlns';
1581
-
1582
- nsPrefix = nsPrefix || findPrefix(defs.xmlns, nsURI);
1583
-
1584
- nsURI = nsURI || defs.xmlns[nsPrefix];
1585
- nsPrefix = nsPrefix === TNS_PREFIX ? '' : (nsPrefix + ':');
1586
-
1587
- parts.push(['<', nsPrefix, name, '>'].join(''));
1588
-
1589
- for (var key in params) {
1590
- if (!params.hasOwnProperty(key)) {
1591
- continue;
1592
- }
1593
- if (key !== nsAttrName) {
1594
- var value = params[key];
1595
- var prefixedKey = (isParts ? '' : nsPrefix) + key;
1596
- parts.push(['<', prefixedKey, '>'].join(''));
1597
- parts.push((typeof value === 'object') ? this.objectToXML(value, key, nsPrefix, nsURI) : xmlEscape(value));
1598
- parts.push(['</', prefixedKey, '>'].join(''));
1599
- }
1600
- }
1601
- parts.push(['</', nsPrefix, name, '>'].join(''));
1602
- return parts.join('');
1603
- };
1604
-
1605
-
1606
- function appendColon(ns) {
1607
- return (ns && ns.charAt(ns.length - 1) !== ':') ? ns + ':' : ns;
1608
- }
1609
-
1610
- function noColonNameSpace(ns) {
1611
- return (ns && ns.charAt(ns.length - 1) === ':') ? ns.substring(0, ns.length - 1) : ns;
1612
- }
1613
-
1614
- WSDL.prototype.isIgnoredNameSpace = function(ns) {
1615
- return this.options.ignoredNamespaces.indexOf(ns) > -1;
1616
- };
1617
-
1618
- WSDL.prototype.filterOutIgnoredNameSpace = function(ns) {
1619
- var namespace = noColonNameSpace(ns);
1620
- return this.isIgnoredNameSpace(namespace) ? '' : namespace;
1621
- };
1622
-
1623
-
1624
-
1625
- /**
1626
- * Convert an object to XML. This is a recursive method as it calls itself.
1627
- *
1628
- * @param {Object} obj the object to convert.
1629
- * @param {String} name the name of the element (if the object being traversed is
1630
- * an element).
1631
- * @param {String} nsPrefix the namespace prefix of the object I.E. xsd.
1632
- * @param {String} nsURI the full namespace of the object I.E. http://w3.org/schema.
1633
- * @param {Boolean} isFirst whether or not this is the first item being traversed.
1634
- * @param {?} xmlnsAttr
1635
- * @param {?} parameterTypeObject
1636
- * @param {NamespaceContext} nsContext Namespace context
1637
- */
1638
- WSDL.prototype.objectToXML = function(obj, name, nsPrefix, nsURI, isFirst, xmlnsAttr, schemaObject, nsContext) {
1639
- var self = this;
1640
- var schema = this.definitions.schemas[nsURI];
1641
-
1642
- var parentNsPrefix = nsPrefix ? nsPrefix.parent : undefined;
1643
- if (typeof parentNsPrefix !== 'undefined') {
1644
- //we got the parentNsPrefix for our array. setting the namespace-variable back to the current namespace string
1645
- nsPrefix = nsPrefix.current;
1646
- }
1647
-
1648
- parentNsPrefix = noColonNameSpace(parentNsPrefix);
1649
- if (this.isIgnoredNameSpace(parentNsPrefix)) {
1650
- parentNsPrefix = '';
1651
- }
1652
-
1653
- var soapHeader = !schema;
1654
- var qualified = schema && schema.$elementFormDefault === 'qualified';
1655
- var parts = [];
1656
- var prefixNamespace = (nsPrefix || qualified) && nsPrefix !== TNS_PREFIX;
1657
-
1658
- var xmlnsAttrib = '';
1659
- if (nsURI && isFirst) {
1660
- if(self.options.overrideRootElement && self.options.overrideRootElement.xmlnsAttributes) {
1661
- self.options.overrideRootElement.xmlnsAttributes.forEach(function(attribute) {
1662
- xmlnsAttrib += ' ' + attribute.name + '="' + attribute.value + '"';
1663
- });
1664
- } else {
1665
- if (prefixNamespace && !this.isIgnoredNameSpace(nsPrefix)) {
1666
- // resolve the prefix namespace
1667
- xmlnsAttrib += ' xmlns:' + nsPrefix + '="' + nsURI + '"';
1668
- }
1669
- // only add default namespace if the schema elementFormDefault is qualified
1670
- if (qualified || soapHeader) xmlnsAttrib += ' xmlns="' + nsURI + '"';
1671
- }
1672
- }
1673
-
1674
- if (!nsContext) {
1675
- nsContext = new NamespaceContext();
1676
- nsContext.declareNamespace(nsPrefix, nsURI);
1677
- } else {
1678
- nsContext.pushContext();
1679
- }
1680
-
1681
- // explicitly use xmlns attribute if available
1682
- if (xmlnsAttr && !(self.options.overrideRootElement && self.options.overrideRootElement.xmlnsAttributes)) {
1683
- xmlnsAttrib = xmlnsAttr;
1684
- }
1685
-
1686
- var ns = '';
1687
-
1688
- if (self.options.overrideRootElement && isFirst) {
1689
- ns = self.options.overrideRootElement.namespace;
1690
- } else if (prefixNamespace && (qualified || isFirst || soapHeader) && !this.isIgnoredNameSpace(nsPrefix)) {
1691
- ns = nsPrefix;
1692
- }
1693
-
1694
- var i, n;
1695
- // start building out XML string.
1696
- if (Array.isArray(obj)) {
1697
- for (i = 0, n = obj.length; i < n; i++) {
1698
- var item = obj[i];
1699
- var arrayAttr = self.processAttributes(item, nsContext),
1700
- correctOuterNsPrefix = parentNsPrefix || ns; //using the parent namespace prefix if given
1701
-
1702
- parts.push(['<', appendColon(correctOuterNsPrefix), name, arrayAttr, xmlnsAttrib, '>'].join(''));
1703
- parts.push(self.objectToXML(item, name, nsPrefix, nsURI, false, null, schemaObject, nsContext));
1704
- parts.push(['</', appendColon(correctOuterNsPrefix), name, '>'].join(''));
1705
- }
1706
- } else if (typeof obj === 'object') {
1707
- for (name in obj) {
1708
- if (!obj.hasOwnProperty(name)) continue;
1709
- //don't process attributes as element
1710
- if (name === self.options.attributesKey) {
1711
- continue;
1712
- }
1713
- //Its the value of a xml object. Return it directly.
1714
- if (name === self.options.xmlKey){
1715
- nsContext.popContext();
1716
- return obj[name];
1717
- }
1718
- //Its the value of an item. Return it directly.
1719
- if (name === self.options.valueKey) {
1720
- nsContext.popContext();
1721
- return xmlEscape(obj[name]);
1722
- }
1723
-
1724
- var child = obj[name];
1725
- if (typeof child === 'undefined') {
1726
- continue;
1727
- }
1728
-
1729
- var attr = self.processAttributes(child, nsContext);
1730
-
1731
- var value = '';
1732
- var nonSubNameSpace = '';
1733
- var emptyNonSubNameSpace = false;
1734
-
1735
- var nameWithNsRegex = /^([^:]+):([^:]+)$/.exec(name);
1736
- if (nameWithNsRegex) {
1737
- nonSubNameSpace = nameWithNsRegex[1] + ':';
1738
- name = nameWithNsRegex[2];
1739
- } else if(name[0] === ':'){
1740
- emptyNonSubNameSpace = true;
1741
- name = name.substr(1);
1742
- }
1743
-
1744
- if (isFirst) {
1745
- value = self.objectToXML(child, name, nsPrefix, nsURI, false, null, schemaObject, nsContext);
1746
- } else {
1747
-
1748
- if (self.definitions.schemas) {
1749
- if (schema) {
1750
- var childSchemaObject = self.findChildSchemaObject(schemaObject, name);
1751
- //find sub namespace if not a primitive
1752
- if (childSchemaObject &&
1753
- ((childSchemaObject.$type && (childSchemaObject.$type.indexOf('xsd:') === -1)) ||
1754
- childSchemaObject.$ref || childSchemaObject.$name)) {
1755
- /*if the base name space of the children is not in the ingoredSchemaNamspaces we use it.
1756
- This is because in some services the child nodes do not need the baseNameSpace.
1757
- */
1758
-
1759
- var childNsPrefix = '';
1760
- var childName = '';
1761
- var childNsURI;
1762
- var childXmlnsAttrib = '';
1763
-
1764
- var elementQName = childSchemaObject.$ref || childSchemaObject.$name;
1765
- if (elementQName) {
1766
- elementQName = splitQName(elementQName);
1767
- childName = elementQName.name;
1768
- if (elementQName.prefix === TNS_PREFIX) {
1769
- // Local element
1770
- childNsURI = childSchemaObject.$targetNamespace;
1771
- childNsPrefix = nsContext.registerNamespace(childNsURI);
1772
- if (this.isIgnoredNameSpace(childNsPrefix)) {
1773
- childNsPrefix = nsPrefix;
1774
- }
1775
- } else {
1776
- childNsPrefix = elementQName.prefix;
1777
- if (this.isIgnoredNameSpace(childNsPrefix)) {
1778
- childNsPrefix = nsPrefix;
1779
- }
1780
- childNsURI = schema.xmlns[childNsPrefix] || self.definitions.xmlns[childNsPrefix];
1781
- }
1782
-
1783
- var unqualified = false;
1784
- // Check qualification form for local elements
1785
- if (childSchemaObject.$name && childSchemaObject.targetNamespace === undefined) {
1786
- if (childSchemaObject.$form === 'unqualified') {
1787
- unqualified = true;
1788
- } else if (childSchemaObject.$form === 'qualified') {
1789
- unqualified = false;
1790
- } else {
1791
- unqualified = schema.$elementFormDefault !== 'qualified';
1792
- }
1793
- }
1794
- if (unqualified) {
1795
- childNsPrefix = '';
1796
- }
1797
-
1798
- if (childNsURI && childNsPrefix) {
1799
- if (nsContext.declareNamespace(childNsPrefix, childNsURI)) {
1800
- childXmlnsAttrib = ' xmlns:' + childNsPrefix + '="' + childNsURI + '"';
1801
- xmlnsAttrib += childXmlnsAttrib;
1802
- }
1803
- }
1804
- }
1805
-
1806
- var resolvedChildSchemaObject;
1807
- if (childSchemaObject.$type) {
1808
- var typeQName = splitQName(childSchemaObject.$type);
1809
- var typePrefix = typeQName.prefix;
1810
- var typeURI = schema.xmlns[typePrefix] || self.definitions.xmlns[typePrefix];
1811
- childNsURI = typeURI;
1812
- if (typeURI !== 'http://www.w3.org/2001/XMLSchema' && typePrefix !== TNS_PREFIX) {
1813
- // Add the prefix/namespace mapping, but not declare it
1814
- nsContext.addNamespace(typePrefix, typeURI);
1815
- }
1816
- resolvedChildSchemaObject =
1817
- self.findSchemaType(typeQName.name, typeURI) || childSchemaObject;
1818
- } else {
1819
- resolvedChildSchemaObject =
1820
- self.findSchemaObject(childNsURI, childName) || childSchemaObject;
1821
- }
1822
-
1823
- if (childSchemaObject.$baseNameSpace && this.options.ignoreBaseNameSpaces) {
1824
- childNsPrefix = nsPrefix;
1825
- childNsURI = nsURI;
1826
- }
1827
-
1828
- if (this.options.ignoreBaseNameSpaces) {
1829
- childNsPrefix = '';
1830
- childNsURI = '';
1831
- }
1832
-
1833
- ns = childNsPrefix;
1834
-
1835
- if (Array.isArray(child)) {
1836
- //for arrays, we need to remember the current namespace
1837
- childNsPrefix = {
1838
- current: childNsPrefix,
1839
- parent: ns
1840
- };
1841
- } else {
1842
- //parent (array) already got the namespace
1843
- childXmlnsAttrib = null;
1844
- }
1845
-
1846
- value = self.objectToXML(child, name, childNsPrefix, childNsURI,
1847
- false, childXmlnsAttrib, resolvedChildSchemaObject, nsContext);
1848
- } else if (obj[self.options.attributesKey] && obj[self.options.attributesKey].xsi_type) {
1849
- //if parent object has complex type defined and child not found in parent
1850
- var completeChildParamTypeObject = self.findChildSchemaObject(
1851
- obj[self.options.attributesKey].xsi_type.type,
1852
- obj[self.options.attributesKey].xsi_type.xmlns);
1853
-
1854
- nonSubNameSpace = obj[self.options.attributesKey].xsi_type.prefix;
1855
- nsContext.addNamespace(obj[self.options.attributesKey].xsi_type.prefix,
1856
- obj[self.options.attributesKey].xsi_type.xmlns);
1857
- value = self.objectToXML(child, name, obj[self.options.attributesKey].xsi_type.prefix,
1858
- obj[self.options.attributesKey].xsi_type.xmlns, false, null, null, nsContext);
1859
- } else {
1860
- if(Array.isArray(child)) {
1861
- name = nonSubNameSpace + name;
1862
- }
1863
-
1864
- value = self.objectToXML(child, name, nsPrefix, nsURI, false, null, null, nsContext);
1865
- }
1866
- } else {
1867
- value = self.objectToXML(child, name, nsPrefix, nsURI, false, null, null, nsContext);
1868
- }
1869
- }
1870
- }
1871
-
1872
- ns = noColonNameSpace(ns);
1873
- if (prefixNamespace && !qualified && isFirst && !self.options.overrideRootElement) {
1874
- ns = nsPrefix;
1875
- } else if (this.isIgnoredNameSpace(ns)) {
1876
- ns = '';
1877
- }
1878
-
1879
- if (!Array.isArray(child)) {
1880
- // start tag
1881
- parts.push(['<', emptyNonSubNameSpace ? '' : appendColon(nonSubNameSpace || ns), name, attr, xmlnsAttrib,
1882
- (child === null ? ' xsi:nil="true"' : ''), '>'].join(''));
1883
- }
1884
- parts.push(value);
1885
- if (!Array.isArray(child)) {
1886
- // end tag
1887
- parts.push(['</', emptyNonSubNameSpace ? '' : appendColon(nonSubNameSpace || ns), name, '>'].join(''));
1888
- }
1889
- }
1890
- } else if (obj !== undefined) {
1891
- parts.push((self.options.escapeXML) ? xmlEscape(obj) : obj);
1892
- }
1893
- nsContext.popContext();
1894
- return parts.join('');
1895
- };
1896
-
1897
- WSDL.prototype.processAttributes = function(child, nsContext) {
1898
- var attr = '';
1899
-
1900
- if(child === null) {
1901
- child = [];
1902
- }
1903
-
1904
- var attrObj = child[this.options.attributesKey];
1905
- if (attrObj && attrObj.xsi_type) {
1906
- var xsiType = attrObj.xsi_type;
1907
-
1908
- var prefix = xsiType.prefix || xsiType.namespace;
1909
- // Generate a new namespace for complex extension if one not provided
1910
- if (!prefix) {
1911
- prefix = nsContext.registerNamespace(xsiType.xmlns);
1912
- } else {
1913
- nsContext.declareNamespace(prefix, xsiType.xmlns);
1914
- }
1915
- xsiType.prefix = prefix;
1916
- }
1917
-
1918
-
1919
- if (attrObj) {
1920
- for (var attrKey in attrObj) {
1921
- //handle complex extension separately
1922
- if (attrKey === 'xsi_type') {
1923
- var attrValue = attrObj[attrKey];
1924
- attr += ' xsi:type="' + attrValue.prefix + ':' + attrValue.type + '"';
1925
- attr += ' xmlns:' + attrValue.prefix + '="' + attrValue.xmlns + '"';
1926
-
1927
- continue;
1928
- } else {
1929
- attr += ' ' + attrKey + '="' + xmlEscape(attrObj[attrKey]) + '"';
1930
- }
1931
- }
1932
- }
1933
-
1934
- return attr;
1935
- };
1936
-
1937
- /**
1938
- * Look up a schema type definition
1939
- * @param name
1940
- * @param nsURI
1941
- * @returns {*}
1942
- */
1943
- WSDL.prototype.findSchemaType = function(name, nsURI) {
1944
- if (!this.definitions.schemas || !name || !nsURI) {
1945
- return null;
1946
- }
1947
-
1948
- var schema = this.definitions.schemas[nsURI];
1949
- if (!schema || !schema.complexTypes) {
1950
- return null;
1951
- }
1952
-
1953
- return schema.complexTypes[name];
1954
- };
1955
-
1956
- WSDL.prototype.findChildSchemaObject = function(parameterTypeObj, childName, backtrace) {
1957
- if (!parameterTypeObj || !childName) {
1958
- return null;
1959
- }
1960
-
1961
- if (!backtrace) {
1962
- backtrace = [];
1963
- }
1964
-
1965
- if (backtrace.indexOf(parameterTypeObj) >= 0) {
1966
- // We've recursed back to ourselves; break.
1967
- return null;
1968
- } else {
1969
- backtrace = backtrace.concat([parameterTypeObj]);
1970
- }
1971
-
1972
- var found = null,
1973
- i = 0,
1974
- child,
1975
- ref;
1976
-
1977
- if (Array.isArray(parameterTypeObj.$lookupTypes) && parameterTypeObj.$lookupTypes.length) {
1978
- var types = parameterTypeObj.$lookupTypes;
1979
-
1980
- for(i = 0; i < types.length; i++) {
1981
- var typeObj = types[i];
1982
-
1983
- if(typeObj.$name === childName) {
1984
- found = typeObj;
1985
- break;
1986
- }
1987
- }
1988
- }
1989
-
1990
- var object = parameterTypeObj;
1991
- if (object.$name === childName && object.name === 'element') {
1992
- return object;
1993
- }
1994
- if (object.$ref) {
1995
- ref = splitQName(object.$ref);
1996
- if (ref.name === childName) {
1997
- return object;
1998
- }
1999
- }
2000
-
2001
- var childNsURI;
2002
- if (object.$type) {
2003
- var typeInfo = splitQName(object.$type);
2004
- if (typeInfo.prefix === TNS_PREFIX) {
2005
- childNsURI = parameterTypeObj.$targetNamespace;
2006
- } else {
2007
- childNsURI = this.definitions.xmlns[typeInfo.prefix];
2008
- }
2009
- var typeDef = this.findSchemaType(typeInfo.name, childNsURI);
2010
- if (typeDef) {
2011
- return this.findChildSchemaObject(typeDef, childName, backtrace);
2012
- }
2013
- }
2014
-
2015
- if (object.children) {
2016
- for (i = 0, child; child = object.children[i]; i++) {
2017
- found = this.findChildSchemaObject(child, childName, backtrace);
2018
- if (found) {
2019
- break;
2020
- }
2021
-
2022
- if (child.$base) {
2023
- var baseQName = splitQName(child.$base);
2024
- var childNameSpace = baseQName.prefix === TNS_PREFIX ? '' : baseQName.prefix;
2025
- childNsURI = this.definitions.xmlns[baseQName.prefix];
2026
-
2027
- var foundBase = this.findSchemaType(baseQName.name, childNsURI);
2028
-
2029
- if (foundBase) {
2030
- found = this.findChildSchemaObject(foundBase, childName, backtrace);
2031
-
2032
- if (found) {
2033
- found.$baseNameSpace = childNameSpace;
2034
- found.$type = childNameSpace + ':' + childName;
2035
- break;
2036
- }
2037
- }
2038
- }
2039
- }
2040
-
2041
- }
2042
-
2043
- if (!found && object.$name === childName) {
2044
- return object;
2045
- }
2046
-
2047
- return found;
2048
- };
2049
-
2050
- WSDL.prototype._parse = function(xml) {
2051
- var self = this,
2052
- p = sax.parser(true),
2053
- stack = [],
2054
- root = null,
2055
- types = null,
2056
- schema = null,
2057
- options = self.options;
2058
-
2059
- p.onopentag = function(node) {
2060
- var nsName = node.name;
2061
- var attrs = node.attributes;
2062
-
2063
- var top = stack[stack.length - 1];
2064
- var name;
2065
- if (top) {
2066
- try {
2067
- top.startElement(stack, nsName, attrs, options);
2068
- } catch (e) {
2069
- if (self.options.strict) {
2070
- throw e;
2071
- } else {
2072
- stack.push(new Element(nsName, attrs, options));
2073
- }
2074
- }
2075
- } else {
2076
- name = splitQName(nsName).name;
2077
- if (name === 'definitions') {
2078
- root = new DefinitionsElement(nsName, attrs, options);
2079
- stack.push(root);
2080
- } else if (name === 'schema') {
2081
- // Shim a structure in here to allow the proper objects to be created when merging back.
2082
- root = new DefinitionsElement('definitions', {}, {});
2083
- types = new TypesElement('types', {}, {});
2084
- schema = new SchemaElement(nsName, attrs, options);
2085
- types.addChild(schema);
2086
- root.addChild(types);
2087
- stack.push(schema);
2088
- } else {
2089
- throw new Error('Unexpected root element of WSDL or include');
2090
- }
2091
- }
2092
- };
2093
-
2094
- p.onclosetag = function(name) {
2095
- var top = stack[stack.length - 1];
2096
- assert(top, 'Unmatched close tag: ' + name);
2097
-
2098
- top.endElement(stack, name);
2099
- };
2100
-
2101
- p.write(xml).close();
2102
-
2103
- return root;
2104
- };
2105
-
2106
- WSDL.prototype._fromXML = function(xml) {
2107
- this.definitions = this._parse(xml);
2108
- this.definitions.descriptions = {
2109
- types:{}
2110
- };
2111
- this.xml = xml;
2112
- };
2113
-
2114
- WSDL.prototype._fromServices = function(services) {
2115
-
2116
- };
2117
-
2118
-
2119
-
2120
- WSDL.prototype._xmlnsMap = function() {
2121
- var xmlns = this.definitions.xmlns;
2122
- var str = '';
2123
- for (var alias in xmlns) {
2124
- if (alias === '' || alias === TNS_PREFIX) {
2125
- continue;
2126
- }
2127
- var ns = xmlns[alias];
2128
- switch (ns) {
2129
- case "http://xml.apache.org/xml-soap" : // apachesoap
2130
- case "http://schemas.xmlsoap.org/wsdl/" : // wsdl
2131
- case "http://schemas.xmlsoap.org/wsdl/soap/" : // wsdlsoap
2132
- case "http://schemas.xmlsoap.org/wsdl/soap12/": // wsdlsoap12
2133
- case "http://schemas.xmlsoap.org/soap/encoding/" : // soapenc
2134
- case "http://www.w3.org/2001/XMLSchema" : // xsd
2135
- continue;
2136
- }
2137
- if (~ns.indexOf('http://schemas.xmlsoap.org/')) {
2138
- continue;
2139
- }
2140
- if (~ns.indexOf('http://www.w3.org/')) {
2141
- continue;
2142
- }
2143
- if (~ns.indexOf('http://xml.apache.org/')) {
2144
- continue;
2145
- }
2146
- str += ' xmlns:' + alias + '="' + ns + '"';
2147
- }
2148
- return str;
2149
- };
2150
-
2151
- /*
2152
- * Have another function to load previous WSDLs as we
2153
- * don't want this to be invoked externally (expect for tests)
2154
- * This will attempt to fix circular dependencies with XSD files,
2155
- * Given
2156
- * - file.wsdl
2157
- * - xs:import namespace="A" schemaLocation: A.xsd
2158
- * - A.xsd
2159
- * - xs:import namespace="B" schemaLocation: B.xsd
2160
- * - B.xsd
2161
- * - xs:import namespace="A" schemaLocation: A.xsd
2162
- * file.wsdl will start loading, import A, then A will import B, which will then import A
2163
- * Because A has already started to load previously it will be returned right away and
2164
- * have an internal circular reference
2165
- * B would then complete loading, then A, then file.wsdl
2166
- * By the time file A starts processing its includes its definitions will be already loaded,
2167
- * this is the only thing that B will depend on when "opening" A
2168
- */
2169
- function open_wsdl_recursive(uri, options, callback) {
2170
- var fromCache,
2171
- WSDL_CACHE;
2172
-
2173
- if (typeof options === 'function') {
2174
- callback = options;
2175
- options = {};
2176
- }
2177
-
2178
- WSDL_CACHE = options.WSDL_CACHE;
2179
-
2180
- if (fromCache = WSDL_CACHE[ uri ]) {
2181
- return callback.call(fromCache, null, fromCache);
2182
- }
2183
-
2184
- return open_wsdl(uri, options, callback);
2185
- }
2186
-
2187
- function open_wsdl(uri, options, callback) {
2188
- if (typeof options === 'function') {
2189
- callback = options;
2190
- options = {};
2191
- }
2192
-
2193
- // initialize cache when calling open_wsdl directly
2194
- var WSDL_CACHE = options.WSDL_CACHE || {};
2195
- var request_headers = options.wsdl_headers;
2196
- var request_options = options.wsdl_options;
2197
-
2198
- var wsdl;
2199
- if (!/^https?:/.test(uri)) {
2200
- debug('Reading file: %s', uri);
2201
- fs.readFile(uri, 'utf8', function(err, definition) {
2202
- if (err) {
2203
- callback(err);
2204
- }
2205
- else {
2206
- wsdl = new WSDL(definition, uri, options);
2207
- WSDL_CACHE[ uri ] = wsdl;
2208
- wsdl.WSDL_CACHE = WSDL_CACHE;
2209
- wsdl.onReady(callback);
2210
- }
2211
- });
2212
- }
2213
- else {
2214
- debug('Reading url: %s', uri);
2215
- var httpClient = options.httpClient || new HttpClient(options);
2216
- httpClient.request(uri, null /* options */, function(err, response, definition) {
2217
- if (err) {
2218
- callback(err);
2219
- } else if (response && response.statusCode === 200) {
2220
- wsdl = new WSDL(definition, uri, options);
2221
- WSDL_CACHE[ uri ] = wsdl;
2222
- wsdl.WSDL_CACHE = WSDL_CACHE;
2223
- wsdl.onReady(callback);
2224
- } else {
2225
- callback(new Error('Invalid WSDL URL: ' + uri + "\n\n\r Code: " + response.statusCode + "\n\n\r Response Body: " + response.body));
2226
- }
2227
- }, request_headers, request_options);
2228
- }
2229
-
2230
- return wsdl;
2231
- }
2232
-
2233
- exports.open_wsdl = open_wsdl;
2234
- exports.WSDL = WSDL;
1
+ /*
2
+ * Copyright (c) 2011 Vinay Pulim <vinay@milewise.com>
3
+ * MIT Licensed
4
+ *
5
+ */
6
+ /*jshint proto:true*/
7
+
8
+ "use strict";
9
+
10
+ var sax = require('sax');
11
+ var inherits = require('util').inherits;
12
+ var HttpClient = require('./http');
13
+ var NamespaceContext = require('./nscontext');
14
+ var fs = require('fs');
15
+ var url = require('url');
16
+ var path = require('path');
17
+ var assert = require('assert').ok;
18
+ var stripBom = require('strip-bom');
19
+ var debug = require('debug')('node-soap');
20
+ var _ = require('lodash');
21
+ var selectn = require('selectn');
22
+ var utils = require('./utils');
23
+ var TNS_PREFIX = utils.TNS_PREFIX;
24
+ var findPrefix = utils.findPrefix;
25
+
26
+ var Primitives = {
27
+ string: 1,
28
+ boolean: 1,
29
+ decimal: 1,
30
+ float: 1,
31
+ double: 1,
32
+ anyType: 1,
33
+ byte: 1,
34
+ int: 1,
35
+ long: 1,
36
+ short: 1,
37
+ negativeInteger: 1,
38
+ nonNegativeInteger: 1,
39
+ positiveInteger: 1,
40
+ nonPositiveInteger:1,
41
+ unsignedByte: 1,
42
+ unsignedInt: 1,
43
+ unsignedLong: 1,
44
+ unsignedShort: 1,
45
+ duration: 0,
46
+ dateTime: 0,
47
+ time: 0,
48
+ date: 0,
49
+ gYearMonth: 0,
50
+ gYear: 0,
51
+ gMonthDay: 0,
52
+ gDay: 0,
53
+ gMonth: 0,
54
+ hexBinary: 0,
55
+ base64Binary: 0,
56
+ anyURI: 0,
57
+ QName: 0,
58
+ NOTATION: 0
59
+ };
60
+
61
+ function splitQName(nsName) {
62
+ var i = typeof nsName === 'string' ? nsName.indexOf(':') : -1;
63
+ return i < 0 ? {prefix: TNS_PREFIX, name: nsName} :
64
+ {prefix: nsName.substring(0, i), name: nsName.substring(i + 1)};
65
+ }
66
+
67
+ function xmlEscape(obj) {
68
+ if (typeof (obj) === 'string') {
69
+ if (obj.substr(0,9) === '<![CDATA[' && obj.substr(-3) === "]]>") {
70
+ return obj;
71
+ }
72
+ return obj
73
+ .replace(/&/g, '&amp;')
74
+ .replace(/</g, '&lt;')
75
+ .replace(/>/g, '&gt;')
76
+ .replace(/"/g, '&quot;')
77
+ .replace(/'/g, '&apos;');
78
+ }
79
+
80
+ return obj;
81
+ }
82
+
83
+ var trimLeft = /^[\s\xA0]+/;
84
+ var trimRight = /[\s\xA0]+$/;
85
+
86
+ function trim(text) {
87
+ return text.replace(trimLeft, '').replace(trimRight, '');
88
+ }
89
+
90
+ function deepMerge(destination, source) {
91
+ return _.mergeWith(destination || {}, source, function(a, b) {
92
+ return _.isArray(a) ? a.concat(b) : undefined;
93
+ });
94
+ }
95
+
96
+ var Element = function(nsName, attrs, options) {
97
+ var parts = splitQName(nsName);
98
+
99
+ this.nsName = nsName;
100
+ this.prefix = parts.prefix;
101
+ this.name = parts.name;
102
+ this.children = [];
103
+ this.xmlns = {};
104
+
105
+ this._initializeOptions(options);
106
+
107
+ for (var key in attrs) {
108
+ var match = /^xmlns:?(.*)$/.exec(key);
109
+ if (match) {
110
+ this.xmlns[match[1] ? match[1] : TNS_PREFIX] = attrs[key];
111
+ }
112
+ else {
113
+ if(key === 'value') {
114
+ this[this.valueKey] = attrs[key];
115
+ } else {
116
+ this['$' + key] = attrs[key];
117
+ }
118
+ }
119
+ }
120
+ if (this.$targetNamespace !== undefined) {
121
+ // Add targetNamespace to the mapping
122
+ this.xmlns[TNS_PREFIX] = this.$targetNamespace;
123
+ }
124
+ };
125
+
126
+ Element.prototype._initializeOptions = function (options) {
127
+ if(options) {
128
+ this.valueKey = options.valueKey || '$value';
129
+ this.xmlKey = options.xmlKey || '$xml';
130
+ this.ignoredNamespaces = options.ignoredNamespaces || [];
131
+ } else {
132
+ this.valueKey = '$value';
133
+ this.xmlKey = '$xml';
134
+ this.ignoredNamespaces = [];
135
+ }
136
+ };
137
+
138
+ Element.prototype.deleteFixedAttrs = function() {
139
+ this.children && this.children.length === 0 && delete this.children;
140
+ this.xmlns && Object.keys(this.xmlns).length === 0 && delete this.xmlns;
141
+ delete this.nsName;
142
+ delete this.prefix;
143
+ delete this.name;
144
+ };
145
+
146
+ Element.prototype.allowedChildren = [];
147
+
148
+ Element.prototype.startElement = function(stack, nsName, attrs, options) {
149
+ if (!this.allowedChildren) {
150
+ return;
151
+ }
152
+
153
+ var ChildClass = this.allowedChildren[splitQName(nsName).name],
154
+ element = null;
155
+
156
+ if (ChildClass) {
157
+ stack.push(new ChildClass(nsName, attrs, options));
158
+ }
159
+ else {
160
+ this.unexpected(nsName);
161
+ }
162
+
163
+ };
164
+
165
+ Element.prototype.endElement = function(stack, nsName) {
166
+ if (this.nsName === nsName) {
167
+ if (stack.length < 2)
168
+ return;
169
+ var parent = stack[stack.length - 2];
170
+ if (this !== stack[0]) {
171
+ _.defaultsDeep(stack[0].xmlns, this.xmlns);
172
+ // delete this.xmlns;
173
+ parent.children.push(this);
174
+ parent.addChild(this);
175
+ }
176
+ stack.pop();
177
+ }
178
+ };
179
+
180
+ Element.prototype.addChild = function(child) {
181
+ return;
182
+ };
183
+
184
+ Element.prototype.unexpected = function(name) {
185
+ throw new Error('Found unexpected element (' + name + ') inside ' + this.nsName);
186
+ };
187
+
188
+ Element.prototype.description = function(definitions) {
189
+ return this.$name || this.name;
190
+ };
191
+
192
+ Element.prototype.init = function() {
193
+ };
194
+
195
+ Element.createSubClass = function() {
196
+ var root = this;
197
+ var subElement = function() {
198
+ root.apply(this, arguments);
199
+ this.init();
200
+ };
201
+ // inherits(subElement, root);
202
+ subElement.prototype.__proto__ = root.prototype;
203
+ return subElement;
204
+ };
205
+
206
+
207
+ var ElementElement = Element.createSubClass();
208
+ var AnyElement = Element.createSubClass();
209
+ var InputElement = Element.createSubClass();
210
+ var OutputElement = Element.createSubClass();
211
+ var SimpleTypeElement = Element.createSubClass();
212
+ var RestrictionElement = Element.createSubClass();
213
+ var ExtensionElement = Element.createSubClass();
214
+ var ChoiceElement = Element.createSubClass();
215
+ var EnumerationElement = Element.createSubClass();
216
+ var ComplexTypeElement = Element.createSubClass();
217
+ var ComplexContentElement = Element.createSubClass();
218
+ var SimpleContentElement = Element.createSubClass();
219
+ var SequenceElement = Element.createSubClass();
220
+ var AllElement = Element.createSubClass();
221
+ var MessageElement = Element.createSubClass();
222
+ var DocumentationElement = Element.createSubClass();
223
+
224
+ var SchemaElement = Element.createSubClass();
225
+ var TypesElement = Element.createSubClass();
226
+ var OperationElement = Element.createSubClass();
227
+ var PortTypeElement = Element.createSubClass();
228
+ var BindingElement = Element.createSubClass();
229
+ var PortElement = Element.createSubClass();
230
+ var ServiceElement = Element.createSubClass();
231
+ var DefinitionsElement = Element.createSubClass();
232
+
233
+ var ElementTypeMap = {
234
+ types: [TypesElement, 'schema documentation'],
235
+ schema: [SchemaElement, 'element complexType simpleType include import'],
236
+ element: [ElementElement, 'annotation complexType'],
237
+ any: [AnyElement, ''],
238
+ simpleType: [SimpleTypeElement, 'restriction'],
239
+ restriction: [RestrictionElement, 'enumeration all choice sequence'],
240
+ extension: [ExtensionElement, 'all sequence choice'],
241
+ choice: [ChoiceElement, 'element sequence choice any'],
242
+ // group: [GroupElement, 'element group'],
243
+ enumeration: [EnumerationElement, ''],
244
+ complexType: [ComplexTypeElement, 'annotation sequence all complexContent simpleContent choice'],
245
+ complexContent: [ComplexContentElement, 'extension'],
246
+ simpleContent: [SimpleContentElement, 'extension'],
247
+ sequence: [SequenceElement, 'element sequence choice any'],
248
+ all: [AllElement, 'element choice'],
249
+
250
+ service: [ServiceElement, 'port documentation'],
251
+ port: [PortElement, 'address documentation'],
252
+ binding: [BindingElement, '_binding SecuritySpec operation documentation'],
253
+ portType: [PortTypeElement, 'operation documentation'],
254
+ message: [MessageElement, 'part documentation'],
255
+ operation: [OperationElement, 'documentation input output fault _operation'],
256
+ input: [InputElement, 'body SecuritySpecRef documentation header'],
257
+ output: [OutputElement, 'body SecuritySpecRef documentation header'],
258
+ fault: [Element, '_fault documentation'],
259
+ definitions: [DefinitionsElement, 'types message portType binding service import documentation'],
260
+ documentation: [DocumentationElement, '']
261
+ };
262
+
263
+ function mapElementTypes(types) {
264
+ var rtn = {};
265
+ types = types.split(' ');
266
+ types.forEach(function(type) {
267
+ rtn[type.replace(/^_/, '')] = (ElementTypeMap[type] || [Element]) [0];
268
+ });
269
+ return rtn;
270
+ }
271
+
272
+ for (var n in ElementTypeMap) {
273
+ var v = ElementTypeMap[n];
274
+ v[0].prototype.allowedChildren = mapElementTypes(v[1]);
275
+ }
276
+
277
+ MessageElement.prototype.init = function() {
278
+ this.element = null;
279
+ this.parts = null;
280
+ };
281
+
282
+ SchemaElement.prototype.init = function() {
283
+ this.complexTypes = {};
284
+ this.types = {};
285
+ this.elements = {};
286
+ this.includes = [];
287
+ };
288
+
289
+ TypesElement.prototype.init = function() {
290
+ this.schemas = {};
291
+ };
292
+
293
+ OperationElement.prototype.init = function() {
294
+ this.input = null;
295
+ this.output = null;
296
+ this.inputSoap = null;
297
+ this.outputSoap = null;
298
+ this.style = '';
299
+ this.soapAction = '';
300
+ };
301
+
302
+ PortTypeElement.prototype.init = function() {
303
+ this.methods = {};
304
+ };
305
+
306
+ BindingElement.prototype.init = function() {
307
+ this.transport = '';
308
+ this.style = '';
309
+ this.methods = {};
310
+ };
311
+
312
+ PortElement.prototype.init = function() {
313
+ this.location = null;
314
+ };
315
+
316
+ ServiceElement.prototype.init = function() {
317
+ this.ports = {};
318
+ };
319
+
320
+ DefinitionsElement.prototype.init = function() {
321
+ if (this.name !== 'definitions')this.unexpected(this.nsName);
322
+ this.messages = {};
323
+ this.portTypes = {};
324
+ this.bindings = {};
325
+ this.services = {};
326
+ this.schemas = {};
327
+ };
328
+
329
+ DocumentationElement.prototype.init = function() {
330
+ };
331
+
332
+ SchemaElement.prototype.merge = function(source) {
333
+ assert(source instanceof SchemaElement);
334
+ if (this.$targetNamespace === source.$targetNamespace) {
335
+ _.merge(this.complexTypes, source.complexTypes);
336
+ _.merge(this.types, source.types);
337
+ _.merge(this.elements, source.elements);
338
+ _.merge(this.xmlns, source.xmlns);
339
+ }
340
+ return this;
341
+ };
342
+
343
+
344
+ SchemaElement.prototype.addChild = function(child) {
345
+ if (child.$name in Primitives)
346
+ return;
347
+ if (child.name === 'include' || child.name === 'import') {
348
+ var location = child.$schemaLocation || child.$location;
349
+ if (location) {
350
+ this.includes.push({
351
+ namespace: child.$namespace || child.$targetNamespace || this.$targetNamespace,
352
+ location: location
353
+ });
354
+ }
355
+ }
356
+ else if (child.name === 'complexType') {
357
+ this.complexTypes[child.$name] = child;
358
+ }
359
+ else if (child.name === 'element') {
360
+ this.elements[child.$name] = child;
361
+ }
362
+ else if (child.$name) {
363
+ this.types[child.$name] = child;
364
+ }
365
+ this.children.pop();
366
+ // child.deleteFixedAttrs();
367
+ };
368
+ //fix#325
369
+ TypesElement.prototype.addChild = function (child) {
370
+ assert(child instanceof SchemaElement);
371
+
372
+ var targetNamespace = child.$targetNamespace;
373
+
374
+ if(!this.schemas.hasOwnProperty(targetNamespace)) {
375
+ this.schemas[targetNamespace] = child;
376
+ } else {
377
+ console.error('Target-Namespace "'+ targetNamespace +'" already in use by another Schema!');
378
+ }
379
+ };
380
+
381
+ InputElement.prototype.addChild = function(child) {
382
+ if (child.name === 'body') {
383
+ this.use = child.$use;
384
+ if (this.use === 'encoded') {
385
+ this.encodingStyle = child.$encodingStyle;
386
+ }
387
+ this.children.pop();
388
+ }
389
+ };
390
+
391
+ OutputElement.prototype.addChild = function(child) {
392
+ if (child.name === 'body') {
393
+ this.use = child.$use;
394
+ if (this.use === 'encoded') {
395
+ this.encodingStyle = child.$encodingStyle;
396
+ }
397
+ this.children.pop();
398
+ }
399
+ };
400
+
401
+ OperationElement.prototype.addChild = function(child) {
402
+ if (child.name === 'operation') {
403
+ this.soapAction = child.$soapAction || '';
404
+ this.style = child.$style || '';
405
+ this.children.pop();
406
+ }
407
+ };
408
+
409
+ BindingElement.prototype.addChild = function(child) {
410
+ if (child.name === 'binding') {
411
+ this.transport = child.$transport;
412
+ this.style = child.$style;
413
+ this.children.pop();
414
+ }
415
+ };
416
+
417
+ PortElement.prototype.addChild = function(child) {
418
+ if (child.name === 'address' && typeof (child.$location) !== 'undefined') {
419
+ this.location = child.$location;
420
+ }
421
+ };
422
+
423
+ DefinitionsElement.prototype.addChild = function(child) {
424
+ var self = this;
425
+ if (child instanceof TypesElement) {
426
+ // Merge types.schemas into definitions.schemas
427
+ _.merge(self.schemas, child.schemas);
428
+ }
429
+ else if (child instanceof MessageElement) {
430
+ self.messages[child.$name] = child;
431
+ }
432
+ else if (child.name === 'import') {
433
+ self.schemas[child.$namespace] = new SchemaElement(child.$namespace, {});
434
+ self.schemas[child.$namespace].addChild(child);
435
+ }
436
+ else if (child instanceof PortTypeElement) {
437
+ self.portTypes[child.$name] = child;
438
+ }
439
+ else if (child instanceof BindingElement) {
440
+ if (child.transport === 'http://schemas.xmlsoap.org/soap/http' ||
441
+ child.transport === 'http://www.w3.org/2003/05/soap/bindings/HTTP/')
442
+ self.bindings[child.$name] = child;
443
+ }
444
+ else if (child instanceof ServiceElement) {
445
+ self.services[child.$name] = child;
446
+ }
447
+ else if (child instanceof DocumentationElement) {
448
+ }
449
+ this.children.pop();
450
+ };
451
+
452
+ MessageElement.prototype.postProcess = function(definitions) {
453
+ var part = null;
454
+ var child;
455
+ var children = this.children || [];
456
+ var ns;
457
+ var nsName;
458
+ var i;
459
+ var type;
460
+
461
+ for (i in children) {
462
+ if ((child = children[i]).name === 'part') {
463
+ part = child;
464
+ break;
465
+ }
466
+ }
467
+
468
+ if (!part) {
469
+ return;
470
+ }
471
+
472
+ if (part.$element) {
473
+ var lookupTypes = [],
474
+ elementChildren ;
475
+
476
+ delete this.parts;
477
+
478
+ nsName = splitQName(part.$element);
479
+ ns = nsName.prefix;
480
+ var schema = definitions.schemas[definitions.xmlns[ns]];
481
+ this.element = schema.elements[nsName.name];
482
+ if(!this.element) {
483
+ debug(nsName.name + " is not present in wsdl and cannot be processed correctly.");
484
+ return;
485
+ }
486
+ this.element.targetNSAlias = ns;
487
+ this.element.targetNamespace = definitions.xmlns[ns];
488
+
489
+ // set the optional $lookupType to be used within `client#_invoke()` when
490
+ // calling `wsdl#objectToDocumentXML()
491
+ this.element.$lookupType = part.$element;
492
+
493
+ elementChildren = this.element.children;
494
+
495
+ // get all nested lookup types (only complex types are followed)
496
+ if (elementChildren.length > 0) {
497
+ for (i = 0; i < elementChildren.length; i++) {
498
+ lookupTypes.push(this._getNestedLookupTypeString(elementChildren[i]));
499
+ }
500
+ }
501
+
502
+ // if nested lookup types where found, prepare them for furter usage
503
+ if (lookupTypes.length > 0) {
504
+ lookupTypes = lookupTypes.
505
+ join('_').
506
+ split('_').
507
+ filter(function removeEmptyLookupTypes (type) {
508
+ return type !== '^';
509
+ });
510
+
511
+ var schemaXmlns = definitions.schemas[this.element.targetNamespace].xmlns;
512
+
513
+ for (i = 0; i < lookupTypes.length; i++) {
514
+ lookupTypes[i] = this._createLookupTypeObject(lookupTypes[i], schemaXmlns);
515
+ }
516
+ }
517
+
518
+ this.element.$lookupTypes = lookupTypes;
519
+
520
+ if (this.element.$type) {
521
+ type = splitQName(this.element.$type);
522
+ var typeNs = schema.xmlns && schema.xmlns[type.prefix] || definitions.xmlns[type.prefix];
523
+
524
+ if (typeNs) {
525
+ if (type.name in Primitives) {
526
+ // this.element = this.element.$type;
527
+ }
528
+ else {
529
+ // first check local mapping of ns alias to namespace
530
+ schema = definitions.schemas[typeNs];
531
+ var ctype = schema.complexTypes[type.name] || schema.types[type.name] || schema.elements[type.name];
532
+
533
+
534
+ if (ctype) {
535
+ this.parts = ctype.description(definitions, schema.xmlns);
536
+ }
537
+ }
538
+ }
539
+ }
540
+ else {
541
+ var method = this.element.description(definitions, schema.xmlns);
542
+ this.parts = method[nsName.name];
543
+ }
544
+
545
+
546
+ this.children.splice(0, 1);
547
+ } else {
548
+ // rpc encoding
549
+ this.parts = {};
550
+ delete this.element;
551
+ for (i = 0; part = this.children[i]; i++) {
552
+ if (part.name === 'documentation') {
553
+ // <wsdl:documentation can be present under <wsdl:message>
554
+ continue;
555
+ }
556
+ assert(part.name === 'part', 'Expected part element');
557
+ nsName = splitQName(part.$type);
558
+ ns = definitions.xmlns[nsName.prefix];
559
+ type = nsName.name;
560
+ var schemaDefinition = definitions.schemas[ns];
561
+ if (typeof schemaDefinition !== 'undefined') {
562
+ this.parts[part.$name] = definitions.schemas[ns].types[type] || definitions.schemas[ns].complexTypes[type];
563
+ } else {
564
+ this.parts[part.$name] = part.$type;
565
+ }
566
+
567
+ if (typeof this.parts[part.$name] === 'object') {
568
+ this.parts[part.$name].prefix = nsName.prefix;
569
+ this.parts[part.$name].xmlns = ns;
570
+ }
571
+
572
+ this.children.splice(i--, 1);
573
+ }
574
+ }
575
+ this.deleteFixedAttrs();
576
+ };
577
+
578
+ /**
579
+ * Takes a given namespaced String(for example: 'alias:property') and creates a lookupType
580
+ * object for further use in as first (lookup) `parameterTypeObj` within the `objectToXML`
581
+ * method and provides an entry point for the already existing code in `findChildSchemaObject`.
582
+ *
583
+ * @method _createLookupTypeObject
584
+ * @param {String} nsString The NS String (for example "alias:type").
585
+ * @param {Object} xmlns The fully parsed `wsdl` definitions object (including all schemas).
586
+ * @returns {Object}
587
+ * @private
588
+ */
589
+ MessageElement.prototype._createLookupTypeObject = function (nsString, xmlns) {
590
+ var splittedNSString = splitQName(nsString),
591
+ nsAlias = splittedNSString.prefix,
592
+ splittedName = splittedNSString.name.split('#'),
593
+ type = splittedName[0],
594
+ name = splittedName[1],
595
+ lookupTypeObj = {};
596
+
597
+ lookupTypeObj.$namespace = xmlns[nsAlias];
598
+ lookupTypeObj.$type = nsAlias + ':' + type;
599
+ lookupTypeObj.$name = name;
600
+
601
+ return lookupTypeObj;
602
+ };
603
+
604
+ /**
605
+ * Iterates through the element and every nested child to find any defined `$type`
606
+ * property and returns it in a underscore ('_') separated String (using '^' as default
607
+ * value if no `$type` property was found).
608
+ *
609
+ * @method _getNestedLookupTypeString
610
+ * @param {Object} element The element which (probably) contains nested `$type` values.
611
+ * @returns {String}
612
+ * @private
613
+ */
614
+ MessageElement.prototype._getNestedLookupTypeString = function (element) {
615
+ var resolvedType = '^',
616
+ excluded = this.ignoredNamespaces.concat('xs'); // do not process $type values wich start with
617
+
618
+ if (element.hasOwnProperty('$type') && typeof element.$type === 'string') {
619
+ if (excluded.indexOf(element.$type.split(':')[0]) === -1) {
620
+ resolvedType += ('_' + element.$type + '#' + element.$name);
621
+ }
622
+ }
623
+
624
+ if (element.children.length > 0) {
625
+ var self = this;
626
+
627
+ element.children.forEach(function (child) {
628
+ var resolvedChildType = self._getNestedLookupTypeString(child).replace(/\^_/, '');
629
+
630
+ if (resolvedChildType && typeof resolvedChildType === 'string') {
631
+ resolvedType += ('_' + resolvedChildType);
632
+ }
633
+ });
634
+ }
635
+
636
+ return resolvedType;
637
+ };
638
+
639
+ OperationElement.prototype.postProcess = function(definitions, tag) {
640
+ var children = this.children;
641
+ for (var i = 0, child; child = children[i]; i++) {
642
+ if (child.name !== 'input' && child.name !== 'output')
643
+ continue;
644
+ if (tag === 'binding') {
645
+ this[child.name] = child;
646
+ children.splice(i--, 1);
647
+ continue;
648
+ }
649
+ var messageName = splitQName(child.$message).name;
650
+ var message = definitions.messages[messageName];
651
+ message.postProcess(definitions);
652
+ if (message.element) {
653
+ definitions.messages[message.element.$name] = message;
654
+ this[child.name] = message.element;
655
+ }
656
+ else {
657
+ this[child.name] = message;
658
+ }
659
+ children.splice(i--, 1);
660
+ }
661
+ this.deleteFixedAttrs();
662
+ };
663
+
664
+ PortTypeElement.prototype.postProcess = function(definitions) {
665
+ var children = this.children;
666
+ if (typeof children === 'undefined')
667
+ return;
668
+ for (var i = 0, child; child = children[i]; i++) {
669
+ if (child.name !== 'operation')
670
+ continue;
671
+ child.postProcess(definitions, 'portType');
672
+ this.methods[child.$name] = child;
673
+ children.splice(i--, 1);
674
+ }
675
+ delete this.$name;
676
+ this.deleteFixedAttrs();
677
+ };
678
+
679
+ BindingElement.prototype.postProcess = function(definitions) {
680
+ var type = splitQName(this.$type).name,
681
+ portType = definitions.portTypes[type],
682
+ style = this.style,
683
+ children = this.children;
684
+ if (portType){
685
+ portType.postProcess(definitions);
686
+ this.methods = portType.methods;
687
+
688
+ for (var i = 0, child; child = children[i]; i++) {
689
+ if (child.name !== 'operation')
690
+ continue;
691
+ child.postProcess(definitions, 'binding');
692
+ children.splice(i--, 1);
693
+ child.style || (child.style = style);
694
+ var method = this.methods[child.$name];
695
+
696
+ if (method) {
697
+ method.style = child.style;
698
+ method.soapAction = child.soapAction;
699
+ method.inputSoap = child.input || null;
700
+ method.outputSoap = child.output || null;
701
+ method.inputSoap && method.inputSoap.deleteFixedAttrs();
702
+ method.outputSoap && method.outputSoap.deleteFixedAttrs();
703
+ }
704
+ }
705
+ }
706
+ delete this.$name;
707
+ delete this.$type;
708
+ this.deleteFixedAttrs();
709
+ };
710
+
711
+ ServiceElement.prototype.postProcess = function(definitions) {
712
+ var children = this.children,
713
+ bindings = definitions.bindings;
714
+ if (children && children.length > 0) {
715
+ for (var i = 0, child; child = children[i]; i++) {
716
+ if (child.name !== 'port')
717
+ continue;
718
+ var bindingName = splitQName(child.$binding).name;
719
+ var binding = bindings[bindingName];
720
+ if (binding) {
721
+ binding.postProcess(definitions);
722
+ this.ports[child.$name] = {
723
+ location: child.location,
724
+ binding: binding
725
+ };
726
+ children.splice(i--, 1);
727
+ }
728
+ }
729
+ }
730
+ delete this.$name;
731
+ this.deleteFixedAttrs();
732
+ };
733
+
734
+
735
+ SimpleTypeElement.prototype.description = function(definitions) {
736
+ var children = this.children;
737
+ for (var i = 0, child; child = children[i]; i++) {
738
+ if (child instanceof RestrictionElement)
739
+ return this.$name + "|" + child.description();
740
+ }
741
+ return {};
742
+ };
743
+
744
+ RestrictionElement.prototype.description = function(definitions, xmlns) {
745
+ var children = this.children;
746
+ var desc;
747
+ for (var i=0, child; child=children[i]; i++) {
748
+ if (child instanceof SequenceElement ||
749
+ child instanceof ChoiceElement) {
750
+ desc = child.description(definitions, xmlns);
751
+ break;
752
+ }
753
+ }
754
+ if (desc && this.$base) {
755
+ var type = splitQName(this.$base),
756
+ typeName = type.name,
757
+ ns = xmlns && xmlns[type.prefix] || definitions.xmlns[type.prefix],
758
+ schema = definitions.schemas[ns],
759
+ typeElement = schema && ( schema.complexTypes[typeName] || schema.types[typeName] || schema.elements[typeName] );
760
+
761
+ desc.getBase = function() {
762
+ return typeElement.description(definitions, schema.xmlns);
763
+ };
764
+ return desc;
765
+ }
766
+
767
+ // then simple element
768
+ var base = this.$base ? this.$base + "|" : "";
769
+ return base + this.children.map(function(child) {
770
+ return child.description();
771
+ }).join(",");
772
+ };
773
+
774
+ ExtensionElement.prototype.description = function(definitions, xmlns) {
775
+ var children = this.children;
776
+ var desc = {};
777
+ for (var i=0, child; child=children[i]; i++) {
778
+ if (child instanceof SequenceElement ||
779
+ child instanceof ChoiceElement) {
780
+ desc = child.description(definitions, xmlns);
781
+ }
782
+ }
783
+ if (this.$base) {
784
+ var type = splitQName(this.$base),
785
+ typeName = type.name,
786
+ ns = xmlns && xmlns[type.prefix] || definitions.xmlns[type.prefix],
787
+ schema = definitions.schemas[ns];
788
+
789
+ if (typeName in Primitives) {
790
+ return this.$base;
791
+ }
792
+ else {
793
+ var typeElement = schema && ( schema.complexTypes[typeName] ||
794
+ schema.types[typeName] || schema.elements[typeName] );
795
+
796
+ if (typeElement) {
797
+ var base = typeElement.description(definitions, schema.xmlns);
798
+ desc = _.defaultsDeep(base, desc);
799
+ }
800
+ }
801
+ }
802
+ return desc;
803
+ };
804
+
805
+ EnumerationElement.prototype.description = function() {
806
+ return this[this.valueKey];
807
+ };
808
+
809
+ ComplexTypeElement.prototype.description = function(definitions, xmlns) {
810
+ var children = this.children || [];
811
+ for (var i=0, child; child=children[i]; i++) {
812
+ if (child instanceof ChoiceElement ||
813
+ child instanceof SequenceElement ||
814
+ child instanceof AllElement ||
815
+ child instanceof SimpleContentElement ||
816
+ child instanceof ComplexContentElement) {
817
+
818
+ return child.description(definitions, xmlns);
819
+ }
820
+ }
821
+ return {};
822
+ };
823
+
824
+ ComplexContentElement.prototype.description = function(definitions, xmlns) {
825
+ var children = this.children;
826
+ for (var i = 0, child; child = children[i]; i++) {
827
+ if (child instanceof ExtensionElement) {
828
+ return child.description(definitions, xmlns);
829
+ }
830
+ }
831
+ return {};
832
+ };
833
+
834
+ SimpleContentElement.prototype.description = function(definitions, xmlns) {
835
+ var children = this.children;
836
+ for (var i = 0, child; child = children[i]; i++) {
837
+ if (child instanceof ExtensionElement) {
838
+ return child.description(definitions, xmlns);
839
+ }
840
+ }
841
+ return {};
842
+ };
843
+
844
+ ElementElement.prototype.description = function(definitions, xmlns) {
845
+ var element = {},
846
+ name = this.$name;
847
+ var isMany = !this.$maxOccurs ? false : (isNaN(this.$maxOccurs) ? (this.$maxOccurs === 'unbounded') : (this.$maxOccurs > 1));
848
+ if (this.$minOccurs !== this.$maxOccurs && isMany) {
849
+ name += '[]';
850
+ }
851
+
852
+ if (xmlns && xmlns[TNS_PREFIX]) {
853
+ this.$targetNamespace = xmlns[TNS_PREFIX];
854
+ }
855
+ var type = this.$type || this.$ref;
856
+ if (type) {
857
+ type = splitQName(type);
858
+ var typeName = type.name,
859
+ ns = xmlns && xmlns[type.prefix] || definitions.xmlns[type.prefix],
860
+ schema = definitions.schemas[ns],
861
+ typeElement = schema && ( this.$type? schema.complexTypes[typeName] || schema.types[typeName] : schema.elements[typeName] );
862
+
863
+ if (ns && definitions.schemas[ns]) {
864
+ xmlns = definitions.schemas[ns].xmlns;
865
+ }
866
+
867
+ if (typeElement && !(typeName in Primitives)) {
868
+
869
+ if (!(typeName in definitions.descriptions.types)) {
870
+
871
+ var elem = {};
872
+ definitions.descriptions.types[typeName] = elem;
873
+ var description = typeElement.description(definitions, xmlns);
874
+ if (typeof description === 'string') {
875
+ elem = description;
876
+ }
877
+ else {
878
+ Object.keys(description).forEach(function (key) {
879
+ elem[key] = description[key];
880
+ });
881
+ }
882
+
883
+ if (this.$ref) {
884
+ element = elem;
885
+ }
886
+ else {
887
+ element[name] = elem;
888
+ }
889
+
890
+ if (typeof elem === 'object') {
891
+ elem.targetNSAlias = type.prefix;
892
+ elem.targetNamespace = ns;
893
+ }
894
+
895
+ definitions.descriptions.types[typeName] = elem;
896
+ }
897
+ else {
898
+ if (this.$ref) {
899
+ element = definitions.descriptions.types[typeName];
900
+ }
901
+ else {
902
+ element[name] = definitions.descriptions.types[typeName];
903
+ }
904
+ }
905
+
906
+ }
907
+ else {
908
+ element[name] = this.$type;
909
+ }
910
+ }
911
+ else {
912
+ var children = this.children;
913
+ element[name] = {};
914
+ for (var i = 0, child; child = children[i]; i++) {
915
+ if (child instanceof ComplexTypeElement) {
916
+ element[name] = child.description(definitions, xmlns);
917
+ }
918
+ }
919
+ }
920
+ return element;
921
+ };
922
+
923
+ AllElement.prototype.description =
924
+ SequenceElement.prototype.description = function(definitions, xmlns) {
925
+ var children = this.children;
926
+ var sequence = {};
927
+ for (var i = 0, child; child = children[i]; i++) {
928
+ if (child instanceof AnyElement) {
929
+ continue;
930
+ }
931
+ var description = child.description(definitions, xmlns);
932
+ for (var key in description) {
933
+ sequence[key] = description[key];
934
+ }
935
+ }
936
+ return sequence;
937
+ };
938
+
939
+ ChoiceElement.prototype.description = function(definitions, xmlns) {
940
+ var children = this.children;
941
+ var choice = {};
942
+ for (var i=0, child; child=children[i]; i++) {
943
+ var description = child.description(definitions, xmlns);
944
+ for (var key in description) {
945
+ choice[key] = description[key];
946
+ }
947
+ }
948
+ return choice;
949
+ };
950
+
951
+ MessageElement.prototype.description = function(definitions) {
952
+ if (this.element) {
953
+ return this.element && this.element.description(definitions);
954
+ }
955
+ var desc = {};
956
+ desc[this.$name] = this.parts;
957
+ return desc;
958
+ };
959
+
960
+ PortTypeElement.prototype.description = function(definitions) {
961
+ var methods = {};
962
+ for (var name in this.methods) {
963
+ var method = this.methods[name];
964
+ methods[name] = method.description(definitions);
965
+ }
966
+ return methods;
967
+ };
968
+
969
+ OperationElement.prototype.description = function(definitions) {
970
+ var inputDesc = this.input ? this.input.description(definitions) : null;
971
+ var outputDesc = this.output ? this.output.description(definitions) : null;
972
+ return {
973
+ input: inputDesc && inputDesc[Object.keys(inputDesc)[0]],
974
+ output: outputDesc && outputDesc[Object.keys(outputDesc)[0]]
975
+ };
976
+ };
977
+
978
+ BindingElement.prototype.description = function(definitions) {
979
+ var methods = {};
980
+ for (var name in this.methods) {
981
+ var method = this.methods[name];
982
+ methods[name] = method.description(definitions);
983
+ }
984
+ return methods;
985
+ };
986
+
987
+ ServiceElement.prototype.description = function(definitions) {
988
+ var ports = {};
989
+ for (var name in this.ports) {
990
+ var port = this.ports[name];
991
+ ports[name] = port.binding.description(definitions);
992
+ }
993
+ return ports;
994
+ };
995
+
996
+ var WSDL = function(definition, uri, options) {
997
+ var self = this,
998
+ fromFunc;
999
+
1000
+ this.uri = uri;
1001
+ this.callback = function() {
1002
+ };
1003
+ this._includesWsdl = [];
1004
+
1005
+ // initialize WSDL cache
1006
+ this.WSDL_CACHE = (options || {}).WSDL_CACHE || {};
1007
+
1008
+ this._initializeOptions(options);
1009
+
1010
+ if (typeof definition === 'string') {
1011
+ definition = stripBom(definition);
1012
+ fromFunc = this._fromXML;
1013
+ }
1014
+ else if (typeof definition === 'object') {
1015
+ fromFunc = this._fromServices;
1016
+ }
1017
+ else {
1018
+ throw new Error('WSDL constructor takes either an XML string or service definition');
1019
+ }
1020
+
1021
+ process.nextTick(function() {
1022
+ try {
1023
+ fromFunc.call(self, definition);
1024
+ } catch (e) {
1025
+ return self.callback(e.message);
1026
+ }
1027
+
1028
+ self.processIncludes(function(err) {
1029
+ var name;
1030
+ if (err) {
1031
+ return self.callback(err);
1032
+ }
1033
+
1034
+ self.definitions.deleteFixedAttrs();
1035
+ var services = self.services = self.definitions.services;
1036
+ if (services) {
1037
+ for (name in services) {
1038
+ services[name].postProcess(self.definitions);
1039
+ }
1040
+ }
1041
+ var complexTypes = self.definitions.complexTypes;
1042
+ if (complexTypes) {
1043
+ for (name in complexTypes) {
1044
+ complexTypes[name].deleteFixedAttrs();
1045
+ }
1046
+ }
1047
+
1048
+ // for document style, for every binding, prepare input message element name to (methodName, output message element name) mapping
1049
+ var bindings = self.definitions.bindings;
1050
+ for (var bindingName in bindings) {
1051
+ var binding = bindings[bindingName];
1052
+ if (typeof binding.style === 'undefined') {
1053
+ binding.style = 'document';
1054
+ }
1055
+ if (binding.style !== 'document')
1056
+ continue;
1057
+ var methods = binding.methods;
1058
+ var topEls = binding.topElements = {};
1059
+ for (var methodName in methods) {
1060
+ if (methods[methodName].input) {
1061
+ var inputName = methods[methodName].input.$name;
1062
+ var outputName="";
1063
+ if(methods[methodName].output )
1064
+ outputName = methods[methodName].output.$name;
1065
+ topEls[inputName] = {"methodName": methodName, "outputName": outputName};
1066
+ }
1067
+ }
1068
+ }
1069
+
1070
+ // prepare soap envelope xmlns definition string
1071
+ self.xmlnsInEnvelope = self._xmlnsMap();
1072
+
1073
+ self.callback(err, self);
1074
+ });
1075
+
1076
+ });
1077
+ };
1078
+
1079
+ WSDL.prototype.ignoredNamespaces = ['tns', 'targetNamespace', 'typedNamespace'];
1080
+
1081
+ WSDL.prototype.ignoreBaseNameSpaces = false;
1082
+
1083
+ WSDL.prototype.valueKey = '$value';
1084
+ WSDL.prototype.xmlKey = '$xml';
1085
+
1086
+ WSDL.prototype._initializeOptions = function (options) {
1087
+ this._originalIgnoredNamespaces = (options || {}).ignoredNamespaces;
1088
+ this.options = {};
1089
+
1090
+ var ignoredNamespaces = options ? options.ignoredNamespaces : null;
1091
+
1092
+ if (ignoredNamespaces &&
1093
+ (Array.isArray(ignoredNamespaces.namespaces) || typeof ignoredNamespaces.namespaces === 'string')) {
1094
+ if (ignoredNamespaces.override) {
1095
+ this.options.ignoredNamespaces = ignoredNamespaces.namespaces;
1096
+ } else {
1097
+ this.options.ignoredNamespaces = this.ignoredNamespaces.concat(ignoredNamespaces.namespaces);
1098
+ }
1099
+ } else {
1100
+ this.options.ignoredNamespaces = this.ignoredNamespaces;
1101
+ }
1102
+
1103
+ this.options.valueKey = options.valueKey || this.valueKey;
1104
+ this.options.xmlKey = options.xmlKey || this.xmlKey;
1105
+ if (options.escapeXML !== undefined) {
1106
+ this.options.escapeXML = options.escapeXML;
1107
+ } else {
1108
+ this.options.escapeXML = true;
1109
+ }
1110
+ if (options.returnFault !== undefined) {
1111
+ this.options.returnFault = options.returnFault;
1112
+ } else {
1113
+ this.options.returnFault = false;
1114
+ }
1115
+ this.options.handleNilAsNull = !!options.handleNilAsNull;
1116
+
1117
+ if (options.namespaceArrayElements !== undefined) {
1118
+ this.options.namespaceArrayElements = options.namespaceArrayElements;
1119
+ } else {
1120
+ this.options.namespaceArrayElements = true;
1121
+ }
1122
+
1123
+ // Allow any request headers to keep passing through
1124
+ this.options.wsdl_headers = options.wsdl_headers;
1125
+ this.options.wsdl_options = options.wsdl_options;
1126
+ if (options.httpClient) {
1127
+ this.options.httpClient = options.httpClient;
1128
+ }
1129
+
1130
+ // The supplied request-object should be passed through
1131
+ if (options.request) {
1132
+ this.options.request = options.request;
1133
+ }
1134
+
1135
+ var ignoreBaseNameSpaces = options ? options.ignoreBaseNameSpaces : null;
1136
+ if (ignoreBaseNameSpaces !== null && typeof ignoreBaseNameSpaces !== 'undefined') {
1137
+ this.options.ignoreBaseNameSpaces = ignoreBaseNameSpaces;
1138
+ } else {
1139
+ this.options.ignoreBaseNameSpaces = this.ignoreBaseNameSpaces;
1140
+ }
1141
+
1142
+ // Works only in client
1143
+ this.options.forceSoap12Headers = options.forceSoap12Headers;
1144
+ this.options.customDeserializer = options.customDeserializer;
1145
+
1146
+ if (options.overrideRootElement !== undefined) {
1147
+ this.options.overrideRootElement = options.overrideRootElement;
1148
+ }
1149
+
1150
+ this.options.useEmptyTag = !!options.useEmptyTag;
1151
+ };
1152
+
1153
+ WSDL.prototype.onReady = function(callback) {
1154
+ if (callback)
1155
+ this.callback = callback;
1156
+ };
1157
+
1158
+ WSDL.prototype._processNextInclude = function(includes, callback) {
1159
+ var self = this,
1160
+ include = includes.shift(),
1161
+ options;
1162
+
1163
+ if (!include)
1164
+ return callback();
1165
+
1166
+ var includePath;
1167
+ if (!/^https?:/.test(self.uri) && !/^https?:/.test(include.location)) {
1168
+ includePath = path.resolve(path.dirname(self.uri), include.location);
1169
+ } else {
1170
+ includePath = url.resolve(self.uri||'', include.location);
1171
+ }
1172
+
1173
+ options = _.assign({}, this.options);
1174
+ // follow supplied ignoredNamespaces option
1175
+ options.ignoredNamespaces = this._originalIgnoredNamespaces || this.options.ignoredNamespaces;
1176
+ options.WSDL_CACHE = this.WSDL_CACHE;
1177
+
1178
+ open_wsdl_recursive(includePath, options, function(err, wsdl) {
1179
+ if (err) {
1180
+ return callback(err);
1181
+ }
1182
+
1183
+ self._includesWsdl.push(wsdl);
1184
+
1185
+ if (wsdl.definitions instanceof DefinitionsElement) {
1186
+ _.mergeWith(self.definitions, wsdl.definitions, function(a,b) {
1187
+ return (a instanceof SchemaElement) ? a.merge(b) : undefined;
1188
+ });
1189
+ } else {
1190
+ self.definitions.schemas[include.namespace || wsdl.definitions.$targetNamespace] = deepMerge(self.definitions.schemas[include.namespace || wsdl.definitions.$targetNamespace], wsdl.definitions);
1191
+ }
1192
+ self._processNextInclude(includes, function(err) {
1193
+ callback(err);
1194
+ });
1195
+ });
1196
+ };
1197
+
1198
+ WSDL.prototype.processIncludes = function(callback) {
1199
+ var schemas = this.definitions.schemas,
1200
+ includes = [];
1201
+
1202
+ for (var ns in schemas) {
1203
+ var schema = schemas[ns];
1204
+ includes = includes.concat(schema.includes || []);
1205
+ }
1206
+
1207
+ this._processNextInclude(includes, callback);
1208
+ };
1209
+
1210
+ WSDL.prototype.describeServices = function() {
1211
+ var services = {};
1212
+ for (var name in this.services) {
1213
+ var service = this.services[name];
1214
+ services[name] = service.description(this.definitions);
1215
+ }
1216
+ return services;
1217
+ };
1218
+
1219
+ WSDL.prototype.toXML = function() {
1220
+ return this.xml || '';
1221
+ };
1222
+
1223
+ WSDL.prototype.xmlToObject = function(xml, callback) {
1224
+ var self = this;
1225
+ var p = typeof callback === 'function' ? {} : sax.parser(true);
1226
+ var objectName = null;
1227
+ var root = {};
1228
+ var schema = {
1229
+ Envelope: {
1230
+ Header: {
1231
+ Security: {
1232
+ UsernameToken: {
1233
+ Username: 'string',
1234
+ Password: 'string'
1235
+ }
1236
+ }
1237
+ },
1238
+ Body: {
1239
+ Fault: {
1240
+ faultcode: 'string',
1241
+ faultstring: 'string',
1242
+ detail: 'string'
1243
+ }
1244
+ }
1245
+ }
1246
+ };
1247
+ var stack = [{name: null, object: root, schema: schema}];
1248
+ var xmlns = {};
1249
+
1250
+ var refs = {}, id; // {id:{hrefs:[],obj:}, ...}
1251
+
1252
+ p.onopentag = function(node) {
1253
+ var nsName = node.name;
1254
+ var attrs = node.attributes;
1255
+
1256
+ var name = splitQName(nsName).name,
1257
+ attributeName,
1258
+ top = stack[stack.length - 1],
1259
+ topSchema = top.schema,
1260
+ elementAttributes = {},
1261
+ hasNonXmlnsAttribute = false,
1262
+ hasNilAttribute = false,
1263
+ obj = {};
1264
+ var originalName = name;
1265
+
1266
+ if (!objectName && top.name === 'Body' && name !== 'Fault') {
1267
+ var message = self.definitions.messages[name];
1268
+ // Support RPC/literal messages where response body contains one element named
1269
+ // after the operation + 'Response'. See http://www.w3.org/TR/wsdl#_names
1270
+ if (!message) {
1271
+ try {
1272
+ // Determine if this is request or response
1273
+ var isInput = false;
1274
+ var isOutput = false;
1275
+ if ((/Response$/).test(name)) {
1276
+ isOutput = true;
1277
+ name = name.replace(/Response$/, '');
1278
+ } else if ((/Request$/).test(name)) {
1279
+ isInput = true;
1280
+ name = name.replace(/Request$/, '');
1281
+ } else if ((/Solicit$/).test(name)) {
1282
+ isInput = true;
1283
+ name = name.replace(/Solicit$/, '');
1284
+ }
1285
+ // Look up the appropriate message as given in the portType's operations
1286
+ var portTypes = self.definitions.portTypes;
1287
+ var portTypeNames = Object.keys(portTypes);
1288
+ // Currently this supports only one portType definition.
1289
+ var portType = portTypes[portTypeNames[0]];
1290
+ if (isInput) {
1291
+ name = portType.methods[name].input.$name;
1292
+ } else {
1293
+ name = portType.methods[name].output.$name;
1294
+ }
1295
+ message = self.definitions.messages[name];
1296
+ // 'cache' this alias to speed future lookups
1297
+ self.definitions.messages[originalName] = self.definitions.messages[name];
1298
+ } catch (e) {
1299
+ if (self.options.returnFault) {
1300
+ p.onerror(e);
1301
+ }
1302
+ }
1303
+ }
1304
+
1305
+ topSchema = message.description(self.definitions);
1306
+ objectName = originalName;
1307
+ }
1308
+
1309
+ if (attrs.href) {
1310
+ id = attrs.href.substr(1);
1311
+ if (!refs[id]) {
1312
+ refs[id] = {hrefs: [], obj: null};
1313
+ }
1314
+ refs[id].hrefs.push({par: top.object, key: name, obj: obj});
1315
+ }
1316
+ if (id = attrs.id) {
1317
+ if (!refs[id]) {
1318
+ refs[id] = {hrefs: [], obj: null};
1319
+ }
1320
+ }
1321
+
1322
+ //Handle element attributes
1323
+ for (attributeName in attrs) {
1324
+ if (/^xmlns:|^xmlns$/.test(attributeName)) {
1325
+ xmlns[splitQName(attributeName).name] = attrs[attributeName];
1326
+ continue;
1327
+ }
1328
+ hasNonXmlnsAttribute = true;
1329
+ elementAttributes[attributeName] = attrs[attributeName];
1330
+ }
1331
+
1332
+ for(attributeName in elementAttributes){
1333
+ var res = splitQName(attributeName);
1334
+ if (res.name === 'nil' && xmlns[res.prefix] === 'http://www.w3.org/2001/XMLSchema-instance' && elementAttributes[attributeName] &&
1335
+ (elementAttributes[attributeName].toLowerCase() === 'true' || elementAttributes[attributeName] === '1')
1336
+ ) {
1337
+ hasNilAttribute = true;
1338
+ break;
1339
+ }
1340
+ }
1341
+
1342
+ if (hasNonXmlnsAttribute) {
1343
+ obj[self.options.attributesKey] = elementAttributes;
1344
+ }
1345
+
1346
+ // Pick up the schema for the type specified in element's xsi:type attribute.
1347
+ var xsiTypeSchema;
1348
+ var xsiType = elementAttributes['xsi:type'];
1349
+ if (xsiType) {
1350
+ var type = splitQName(xsiType);
1351
+ var typeURI;
1352
+ if (type.prefix === TNS_PREFIX) {
1353
+ // In case of xsi:type = "MyType"
1354
+ typeURI = xmlns[type.prefix] || xmlns.xmlns;
1355
+ } else {
1356
+ typeURI = xmlns[type.prefix];
1357
+ }
1358
+ var typeDef = self.findSchemaObject(typeURI, type.name);
1359
+ if (typeDef) {
1360
+ xsiTypeSchema = typeDef.description(self.definitions);
1361
+ }
1362
+ }
1363
+
1364
+ if (topSchema && topSchema[name + '[]']) {
1365
+ name = name + '[]';
1366
+ }
1367
+ stack.push({name: originalName, object: obj, schema: (xsiTypeSchema || (topSchema && topSchema[name])), id: attrs.id, nil: hasNilAttribute});
1368
+ };
1369
+
1370
+ p.onclosetag = function(nsName) {
1371
+ var cur = stack.pop(),
1372
+ obj = cur.object,
1373
+ top = stack[stack.length - 1],
1374
+ topObject = top.object,
1375
+ topSchema = top.schema,
1376
+ name = splitQName(nsName).name;
1377
+
1378
+ if (typeof cur.schema === 'string' && (cur.schema === 'string' || cur.schema.split(':')[1] === 'string')) {
1379
+ if (typeof obj === 'object' && Object.keys(obj).length === 0) obj = cur.object = '';
1380
+ }
1381
+
1382
+ if (cur.nil === true) {
1383
+ if (self.options.handleNilAsNull) {
1384
+ obj = null;
1385
+ } else {
1386
+ return;
1387
+ }
1388
+ }
1389
+
1390
+ if (_.isPlainObject(obj) && !Object.keys(obj).length) {
1391
+ obj = null;
1392
+ }
1393
+
1394
+ if (topSchema && topSchema[name + '[]']) {
1395
+ if (!topObject[name]) {
1396
+ topObject[name] = [];
1397
+ }
1398
+ topObject[name].push(obj);
1399
+ } else if (name in topObject) {
1400
+ if (!Array.isArray(topObject[name])) {
1401
+ topObject[name] = [topObject[name]];
1402
+ }
1403
+ topObject[name].push(obj);
1404
+ } else {
1405
+ topObject[name] = obj;
1406
+ }
1407
+
1408
+ if (cur.id) {
1409
+ refs[cur.id].obj = obj;
1410
+ }
1411
+ };
1412
+
1413
+ p.oncdata = function (text) {
1414
+ var originalText = text;
1415
+ text = trim(text);
1416
+ if (!text.length) {
1417
+ return;
1418
+ }
1419
+
1420
+ if (/<\?xml[\s\S]+\?>/.test(text)) {
1421
+ var top = stack[stack.length - 1];
1422
+ var value = self.xmlToObject(text);
1423
+ if (top.object[self.options.attributesKey]) {
1424
+ top.object[self.options.valueKey] = value;
1425
+ } else {
1426
+ top.object = value;
1427
+ }
1428
+ } else {
1429
+ p.ontext(originalText);
1430
+ }
1431
+ };
1432
+
1433
+ p.onerror = function(e) {
1434
+ p.resume();
1435
+ throw {
1436
+ Fault: {
1437
+ faultcode: 500,
1438
+ faultstring: 'Invalid XML',
1439
+ detail: new Error(e).message,
1440
+ statusCode: 500
1441
+ }
1442
+ };
1443
+ };
1444
+
1445
+ p.ontext = function(text) {
1446
+ var originalText = text;
1447
+ text = trim(text);
1448
+ if (!text.length) {
1449
+ return;
1450
+ }
1451
+
1452
+ var top = stack[stack.length - 1];
1453
+ var name = splitQName(top.schema).name,
1454
+ value;
1455
+ if (self.options && self.options.customDeserializer && self.options.customDeserializer[name]) {
1456
+ value = self.options.customDeserializer[name](text, top);
1457
+ }
1458
+ else {
1459
+ if (name === 'int' || name === 'integer') {
1460
+ value = parseInt(text, 10);
1461
+ } else if (name === 'bool' || name === 'boolean') {
1462
+ value = text.toLowerCase() === 'true' || text === '1';
1463
+ } else if (name === 'dateTime' || name === 'date') {
1464
+ value = new Date(text);
1465
+ } else {
1466
+ if (self.options.preserveWhitespace) {
1467
+ text = originalText;
1468
+ }
1469
+ // handle string or other types
1470
+ if (typeof top.object !== 'string') {
1471
+ value = text;
1472
+ } else {
1473
+ value = top.object + text;
1474
+ }
1475
+ }
1476
+ }
1477
+
1478
+ if (top.object[self.options.attributesKey]) {
1479
+ top.object[self.options.valueKey] = value;
1480
+ } else {
1481
+ top.object = value;
1482
+ }
1483
+ };
1484
+
1485
+ if (typeof callback === 'function') {
1486
+ // we be streaming
1487
+ var saxStream = sax.createStream(true);
1488
+ saxStream.on('opentag', p.onopentag);
1489
+ saxStream.on('closetag', p.onclosetag);
1490
+ saxStream.on('cdata', p.oncdata);
1491
+ saxStream.on('text', p.ontext);
1492
+ xml.pipe(saxStream)
1493
+ .on('error', function (err) {
1494
+ callback(err);
1495
+ })
1496
+ .on('end', function () {
1497
+ var r;
1498
+ try {
1499
+ r = finish();
1500
+ } catch (e) {
1501
+ return callback(e);
1502
+ }
1503
+ callback(null, r);
1504
+ });
1505
+ return;
1506
+ }
1507
+ p.write(xml).close();
1508
+
1509
+ return finish();
1510
+
1511
+ function finish() {
1512
+ // MultiRef support: merge objects instead of replacing
1513
+ for (var n in refs) {
1514
+ var ref = refs[n];
1515
+ for (var i = 0; i < ref.hrefs.length; i++) {
1516
+ _.assign(ref.hrefs[i].obj, ref.obj);
1517
+ }
1518
+ }
1519
+
1520
+ if (root.Envelope) {
1521
+ var body = root.Envelope.Body;
1522
+ if (body && body.Fault) {
1523
+ var code = selectn('faultcode.$value', body.Fault) || selectn('faultcode', body.Fault);
1524
+ var string = selectn('faultstring.$value', body.Fault) || selectn('faultstring', body.Fault);
1525
+ var detail = selectn('detail.$value', body.Fault) || selectn('detail.message', body.Fault);
1526
+ var error = new Error(code + ': ' + string + (detail ? ': ' + detail : ''));
1527
+ error.root = root;
1528
+ throw error;
1529
+ }
1530
+ return root.Envelope;
1531
+ }
1532
+ return root;
1533
+ }
1534
+ };
1535
+
1536
+ /**
1537
+ * Look up a XSD type or element by namespace URI and name
1538
+ * @param {String} nsURI Namespace URI
1539
+ * @param {String} qname Local or qualified name
1540
+ * @returns {*} The XSD type/element definition
1541
+ */
1542
+ WSDL.prototype.findSchemaObject = function(nsURI, qname) {
1543
+ if (!nsURI || !qname) {
1544
+ return null;
1545
+ }
1546
+
1547
+ var def = null;
1548
+
1549
+ if (this.definitions.schemas) {
1550
+ var schema = this.definitions.schemas[nsURI];
1551
+ if (schema) {
1552
+ if (qname.indexOf(':') !== -1) {
1553
+ qname = qname.substring(qname.indexOf(':') + 1, qname.length);
1554
+ }
1555
+
1556
+ // if the client passed an input element which has a `$lookupType` property instead of `$type`
1557
+ // the `def` is found in `schema.elements`.
1558
+ def = schema.complexTypes[qname] || schema.types[qname] || schema.elements[qname];
1559
+ }
1560
+ }
1561
+
1562
+ return def;
1563
+ };
1564
+
1565
+ /**
1566
+ * Create document style xml string from the parameters
1567
+ * @param {String} name
1568
+ * @param {*} params
1569
+ * @param {String} nsPrefix
1570
+ * @param {String} nsURI
1571
+ * @param {String} type
1572
+ */
1573
+ WSDL.prototype.objectToDocumentXML = function(name, params, nsPrefix, nsURI, type) {
1574
+ //If user supplies XML already, just use that. XML Declaration should not be present.
1575
+ if (params && params._xml) {
1576
+ return params._xml;
1577
+ }
1578
+ var args = {};
1579
+ args[name] = params;
1580
+ var parameterTypeObj = type ? this.findSchemaObject(nsURI, type) : null;
1581
+ return this.objectToXML(args, null, nsPrefix, nsURI, true, null, parameterTypeObj);
1582
+ };
1583
+
1584
+ /**
1585
+ * Create RPC style xml string from the parameters
1586
+ * @param {String} name
1587
+ * @param {*} params
1588
+ * @param {String} nsPrefix
1589
+ * @param {String} nsURI
1590
+ * @returns {string}
1591
+ */
1592
+ WSDL.prototype.objectToRpcXML = function(name, params, nsPrefix, nsURI,isParts) {
1593
+ var parts = [];
1594
+ var defs = this.definitions;
1595
+ var nsAttrName = '_xmlns';
1596
+
1597
+ nsPrefix = nsPrefix || findPrefix(defs.xmlns, nsURI);
1598
+
1599
+ nsURI = nsURI || defs.xmlns[nsPrefix];
1600
+ nsPrefix = nsPrefix === TNS_PREFIX ? '' : (nsPrefix + ':');
1601
+
1602
+ parts.push(['<', nsPrefix, name, '>'].join(''));
1603
+
1604
+ for (var key in params) {
1605
+ if (!params.hasOwnProperty(key)) {
1606
+ continue;
1607
+ }
1608
+ if (key !== nsAttrName) {
1609
+ var value = params[key];
1610
+ var prefixedKey = (isParts ? '' : nsPrefix) + key;
1611
+ parts.push(['<', prefixedKey, '>'].join(''));
1612
+ parts.push((typeof value === 'object') ? this.objectToXML(value, key, nsPrefix, nsURI) : xmlEscape(value));
1613
+ parts.push(['</', prefixedKey, '>'].join(''));
1614
+ }
1615
+ }
1616
+ parts.push(['</', nsPrefix, name, '>'].join(''));
1617
+ return parts.join('');
1618
+ };
1619
+
1620
+
1621
+ function appendColon(ns) {
1622
+ return (ns && ns.charAt(ns.length - 1) !== ':') ? ns + ':' : ns;
1623
+ }
1624
+
1625
+ function noColonNameSpace(ns) {
1626
+ return (ns && ns.charAt(ns.length - 1) === ':') ? ns.substring(0, ns.length - 1) : ns;
1627
+ }
1628
+
1629
+ WSDL.prototype.isIgnoredNameSpace = function(ns) {
1630
+ return this.options.ignoredNamespaces.indexOf(ns) > -1;
1631
+ };
1632
+
1633
+ WSDL.prototype.filterOutIgnoredNameSpace = function(ns) {
1634
+ var namespace = noColonNameSpace(ns);
1635
+ return this.isIgnoredNameSpace(namespace) ? '' : namespace;
1636
+ };
1637
+
1638
+
1639
+
1640
+ /**
1641
+ * Convert an object to XML. This is a recursive method as it calls itself.
1642
+ *
1643
+ * @param {Object} obj the object to convert.
1644
+ * @param {String} name the name of the element (if the object being traversed is
1645
+ * an element).
1646
+ * @param {String} nsPrefix the namespace prefix of the object I.E. xsd.
1647
+ * @param {String} nsURI the full namespace of the object I.E. http://w3.org/schema.
1648
+ * @param {Boolean} isFirst whether or not this is the first item being traversed.
1649
+ * @param {?} xmlnsAttr
1650
+ * @param {?} parameterTypeObject
1651
+ * @param {NamespaceContext} nsContext Namespace context
1652
+ */
1653
+ WSDL.prototype.objectToXML = function(obj, name, nsPrefix, nsURI, isFirst, xmlnsAttr, schemaObject, nsContext) {
1654
+ var self = this;
1655
+ var schema = this.definitions.schemas[nsURI];
1656
+
1657
+ var parentNsPrefix = nsPrefix ? nsPrefix.parent : undefined;
1658
+ if (typeof parentNsPrefix !== 'undefined') {
1659
+ //we got the parentNsPrefix for our array. setting the namespace-variable back to the current namespace string
1660
+ nsPrefix = nsPrefix.current;
1661
+ }
1662
+
1663
+ parentNsPrefix = noColonNameSpace(parentNsPrefix);
1664
+ if (this.isIgnoredNameSpace(parentNsPrefix)) {
1665
+ parentNsPrefix = '';
1666
+ }
1667
+
1668
+ var soapHeader = !schema;
1669
+ var qualified = schema && schema.$elementFormDefault === 'qualified';
1670
+ var parts = [];
1671
+ var prefixNamespace = (nsPrefix || qualified) && nsPrefix !== TNS_PREFIX;
1672
+
1673
+ var xmlnsAttrib = '';
1674
+ if (nsURI && isFirst) {
1675
+ if(self.options.overrideRootElement && self.options.overrideRootElement.xmlnsAttributes) {
1676
+ self.options.overrideRootElement.xmlnsAttributes.forEach(function(attribute) {
1677
+ xmlnsAttrib += ' ' + attribute.name + '="' + attribute.value + '"';
1678
+ });
1679
+ } else {
1680
+ if (prefixNamespace && !this.isIgnoredNameSpace(nsPrefix)) {
1681
+ // resolve the prefix namespace
1682
+ xmlnsAttrib += ' xmlns:' + nsPrefix + '="' + nsURI + '"';
1683
+ }
1684
+ // only add default namespace if the schema elementFormDefault is qualified
1685
+ if (qualified || soapHeader) xmlnsAttrib += ' xmlns="' + nsURI + '"';
1686
+ }
1687
+ }
1688
+
1689
+ if (!nsContext) {
1690
+ nsContext = new NamespaceContext();
1691
+ nsContext.declareNamespace(nsPrefix, nsURI);
1692
+ } else {
1693
+ nsContext.pushContext();
1694
+ }
1695
+
1696
+ // explicitly use xmlns attribute if available
1697
+ if (xmlnsAttr && !(self.options.overrideRootElement && self.options.overrideRootElement.xmlnsAttributes)) {
1698
+ xmlnsAttrib = xmlnsAttr;
1699
+ }
1700
+
1701
+ var ns = '';
1702
+
1703
+ if (self.options.overrideRootElement && isFirst) {
1704
+ ns = self.options.overrideRootElement.namespace;
1705
+ } else if (prefixNamespace && (qualified || isFirst || soapHeader) && !this.isIgnoredNameSpace(nsPrefix)) {
1706
+ ns = nsPrefix;
1707
+ }
1708
+
1709
+ var i, n;
1710
+ // start building out XML string.
1711
+ if (Array.isArray(obj)) {
1712
+ for (i = 0, n = obj.length; i < n; i++) {
1713
+ var item = obj[i];
1714
+ var arrayAttr = self.processAttributes(item, nsContext),
1715
+ correctOuterNsPrefix = parentNsPrefix || ns; //using the parent namespace prefix if given
1716
+
1717
+ var body = self.objectToXML(item, name, nsPrefix, nsURI, false, null, schemaObject, nsContext);
1718
+
1719
+ var openingTagParts = ['<', appendColon(correctOuterNsPrefix), name, arrayAttr, xmlnsAttrib];
1720
+
1721
+ if (body === '' && self.options.useEmptyTag) {
1722
+ // Use empty (self-closing) tags if no contents
1723
+ openingTagParts.push(' />');
1724
+ parts.push(openingTagParts.join(''));
1725
+ } else {
1726
+ openingTagParts.push('>');
1727
+ if(self.options.namespaceArrayElements || i === 0) {
1728
+ parts.push(openingTagParts.join(''));
1729
+ }
1730
+ parts.push(body);
1731
+ if(self.options.namespaceArrayElements || i === n-1) {
1732
+ parts.push(['</', appendColon(correctOuterNsPrefix), name, '>'].join(''));
1733
+ }
1734
+ }
1735
+ }
1736
+ } else if (typeof obj === 'object') {
1737
+ for (name in obj) {
1738
+ if (!obj.hasOwnProperty(name)) continue;
1739
+ //don't process attributes as element
1740
+ if (name === self.options.attributesKey) {
1741
+ continue;
1742
+ }
1743
+ //Its the value of a xml object. Return it directly.
1744
+ if (name === self.options.xmlKey){
1745
+ nsContext.popContext();
1746
+ return obj[name];
1747
+ }
1748
+ //Its the value of an item. Return it directly.
1749
+ if (name === self.options.valueKey) {
1750
+ nsContext.popContext();
1751
+ return xmlEscape(obj[name]);
1752
+ }
1753
+
1754
+ var child = obj[name];
1755
+ if (typeof child === 'undefined') {
1756
+ continue;
1757
+ }
1758
+
1759
+ var attr = self.processAttributes(child, nsContext);
1760
+
1761
+ var value = '';
1762
+ var nonSubNameSpace = '';
1763
+ var emptyNonSubNameSpace = false;
1764
+
1765
+ var nameWithNsRegex = /^([^:]+):([^:]+)$/.exec(name);
1766
+ if (nameWithNsRegex) {
1767
+ nonSubNameSpace = nameWithNsRegex[1] + ':';
1768
+ name = nameWithNsRegex[2];
1769
+ } else if(name[0] === ':'){
1770
+ emptyNonSubNameSpace = true;
1771
+ name = name.substr(1);
1772
+ }
1773
+
1774
+ if (isFirst) {
1775
+ value = self.objectToXML(child, name, nsPrefix, nsURI, false, null, schemaObject, nsContext);
1776
+ } else {
1777
+
1778
+ if (self.definitions.schemas) {
1779
+ if (schema) {
1780
+ var childSchemaObject = self.findChildSchemaObject(schemaObject, name);
1781
+ //find sub namespace if not a primitive
1782
+ if (childSchemaObject &&
1783
+ ((childSchemaObject.$type && (childSchemaObject.$type.indexOf('xsd:') === -1)) ||
1784
+ childSchemaObject.$ref || childSchemaObject.$name)) {
1785
+ /*if the base name space of the children is not in the ingoredSchemaNamspaces we use it.
1786
+ This is because in some services the child nodes do not need the baseNameSpace.
1787
+ */
1788
+
1789
+ var childNsPrefix = '';
1790
+ var childName = '';
1791
+ var childNsURI;
1792
+ var childXmlnsAttrib = '';
1793
+
1794
+ var elementQName = childSchemaObject.$ref || childSchemaObject.$name;
1795
+ if (elementQName) {
1796
+ elementQName = splitQName(elementQName);
1797
+ childName = elementQName.name;
1798
+ if (elementQName.prefix === TNS_PREFIX) {
1799
+ // Local element
1800
+ childNsURI = childSchemaObject.$targetNamespace;
1801
+ childNsPrefix = nsContext.registerNamespace(childNsURI);
1802
+ if (this.isIgnoredNameSpace(childNsPrefix)) {
1803
+ childNsPrefix = nsPrefix;
1804
+ }
1805
+ } else {
1806
+ childNsPrefix = elementQName.prefix;
1807
+ if (this.isIgnoredNameSpace(childNsPrefix)) {
1808
+ childNsPrefix = nsPrefix;
1809
+ }
1810
+ childNsURI = schema.xmlns[childNsPrefix] || self.definitions.xmlns[childNsPrefix];
1811
+ }
1812
+
1813
+ var unqualified = false;
1814
+ // Check qualification form for local elements
1815
+ if (childSchemaObject.$name && childSchemaObject.targetNamespace === undefined) {
1816
+ if (childSchemaObject.$form === 'unqualified') {
1817
+ unqualified = true;
1818
+ } else if (childSchemaObject.$form === 'qualified') {
1819
+ unqualified = false;
1820
+ } else {
1821
+ unqualified = schema.$elementFormDefault !== 'qualified';
1822
+ }
1823
+ }
1824
+ if (unqualified) {
1825
+ childNsPrefix = '';
1826
+ }
1827
+
1828
+ if (childNsURI && childNsPrefix) {
1829
+ if (nsContext.declareNamespace(childNsPrefix, childNsURI)) {
1830
+ childXmlnsAttrib = ' xmlns:' + childNsPrefix + '="' + childNsURI + '"';
1831
+ xmlnsAttrib += childXmlnsAttrib;
1832
+ }
1833
+ }
1834
+ }
1835
+
1836
+ var resolvedChildSchemaObject;
1837
+ if (childSchemaObject.$type) {
1838
+ var typeQName = splitQName(childSchemaObject.$type);
1839
+ var typePrefix = typeQName.prefix;
1840
+ var typeURI = schema.xmlns[typePrefix] || self.definitions.xmlns[typePrefix];
1841
+ childNsURI = typeURI;
1842
+ if (typeURI !== 'http://www.w3.org/2001/XMLSchema' && typePrefix !== TNS_PREFIX) {
1843
+ // Add the prefix/namespace mapping, but not declare it
1844
+ nsContext.addNamespace(typePrefix, typeURI);
1845
+ }
1846
+ resolvedChildSchemaObject =
1847
+ self.findSchemaType(typeQName.name, typeURI) || childSchemaObject;
1848
+ } else {
1849
+ resolvedChildSchemaObject =
1850
+ self.findSchemaObject(childNsURI, childName) || childSchemaObject;
1851
+ }
1852
+
1853
+ if (childSchemaObject.$baseNameSpace && this.options.ignoreBaseNameSpaces) {
1854
+ childNsPrefix = nsPrefix;
1855
+ childNsURI = nsURI;
1856
+ }
1857
+
1858
+ if (this.options.ignoreBaseNameSpaces) {
1859
+ childNsPrefix = '';
1860
+ childNsURI = '';
1861
+ }
1862
+
1863
+ ns = childNsPrefix;
1864
+
1865
+ if (Array.isArray(child)) {
1866
+ //for arrays, we need to remember the current namespace
1867
+ childNsPrefix = {
1868
+ current: childNsPrefix,
1869
+ parent: ns
1870
+ };
1871
+ } else {
1872
+ //parent (array) already got the namespace
1873
+ childXmlnsAttrib = null;
1874
+ }
1875
+
1876
+ value = self.objectToXML(child, name, childNsPrefix, childNsURI,
1877
+ false, childXmlnsAttrib, resolvedChildSchemaObject, nsContext);
1878
+ } else if (obj[self.options.attributesKey] && obj[self.options.attributesKey].xsi_type) {
1879
+ //if parent object has complex type defined and child not found in parent
1880
+ var completeChildParamTypeObject = self.findChildSchemaObject(
1881
+ obj[self.options.attributesKey].xsi_type.type,
1882
+ obj[self.options.attributesKey].xsi_type.xmlns);
1883
+
1884
+ nonSubNameSpace = obj[self.options.attributesKey].xsi_type.prefix;
1885
+ nsContext.addNamespace(obj[self.options.attributesKey].xsi_type.prefix,
1886
+ obj[self.options.attributesKey].xsi_type.xmlns);
1887
+ value = self.objectToXML(child, name, obj[self.options.attributesKey].xsi_type.prefix,
1888
+ obj[self.options.attributesKey].xsi_type.xmlns, false, null, null, nsContext);
1889
+ } else {
1890
+ if(Array.isArray(child)) {
1891
+ name = nonSubNameSpace + name;
1892
+ }
1893
+
1894
+ value = self.objectToXML(child, name, nsPrefix, nsURI, false, null, null, nsContext);
1895
+ }
1896
+ } else {
1897
+ value = self.objectToXML(child, name, nsPrefix, nsURI, false, null, null, nsContext);
1898
+ }
1899
+ }
1900
+ }
1901
+
1902
+ ns = noColonNameSpace(ns);
1903
+ if (prefixNamespace && !qualified && isFirst && !self.options.overrideRootElement) {
1904
+ ns = nsPrefix;
1905
+ } else if (this.isIgnoredNameSpace(ns)) {
1906
+ ns = '';
1907
+ }
1908
+
1909
+ var useEmptyTag = !value && self.options.useEmptyTag;
1910
+ if (!Array.isArray(child)) {
1911
+ // start tag
1912
+ parts.push(['<', emptyNonSubNameSpace ? '' : appendColon(nonSubNameSpace || ns), name, attr, xmlnsAttrib,
1913
+ (child === null ? ' xsi:nil="true"' : ''),
1914
+ useEmptyTag ? ' />' : '>'
1915
+ ].join(''));
1916
+ }
1917
+
1918
+ if (!useEmptyTag) {
1919
+ parts.push(value);
1920
+ if (!Array.isArray(child)) {
1921
+ // end tag
1922
+ parts.push(['</', emptyNonSubNameSpace ? '' : appendColon(nonSubNameSpace || ns), name, '>'].join(''));
1923
+ }
1924
+ }
1925
+ }
1926
+ } else if (obj !== undefined) {
1927
+ parts.push((self.options.escapeXML) ? xmlEscape(obj) : obj);
1928
+ }
1929
+ nsContext.popContext();
1930
+ return parts.join('');
1931
+ };
1932
+
1933
+ WSDL.prototype.processAttributes = function(child, nsContext) {
1934
+ var attr = '';
1935
+
1936
+ if(child === null) {
1937
+ child = [];
1938
+ }
1939
+
1940
+ var attrObj = child[this.options.attributesKey];
1941
+ if (attrObj && attrObj.xsi_type) {
1942
+ var xsiType = attrObj.xsi_type;
1943
+
1944
+ var prefix = xsiType.prefix || xsiType.namespace;
1945
+ // Generate a new namespace for complex extension if one not provided
1946
+ if (!prefix) {
1947
+ prefix = nsContext.registerNamespace(xsiType.xmlns);
1948
+ } else {
1949
+ nsContext.declareNamespace(prefix, xsiType.xmlns);
1950
+ }
1951
+ xsiType.prefix = prefix;
1952
+ }
1953
+
1954
+
1955
+ if (attrObj) {
1956
+ for (var attrKey in attrObj) {
1957
+ //handle complex extension separately
1958
+ if (attrKey === 'xsi_type') {
1959
+ var attrValue = attrObj[attrKey];
1960
+ attr += ' xsi:type="' + attrValue.prefix + ':' + attrValue.type + '"';
1961
+ attr += ' xmlns:' + attrValue.prefix + '="' + attrValue.xmlns + '"';
1962
+
1963
+ continue;
1964
+ } else {
1965
+ attr += ' ' + attrKey + '="' + xmlEscape(attrObj[attrKey]) + '"';
1966
+ }
1967
+ }
1968
+ }
1969
+
1970
+ return attr;
1971
+ };
1972
+
1973
+ /**
1974
+ * Look up a schema type definition
1975
+ * @param name
1976
+ * @param nsURI
1977
+ * @returns {*}
1978
+ */
1979
+ WSDL.prototype.findSchemaType = function(name, nsURI) {
1980
+ if (!this.definitions.schemas || !name || !nsURI) {
1981
+ return null;
1982
+ }
1983
+
1984
+ var schema = this.definitions.schemas[nsURI];
1985
+ if (!schema || !schema.complexTypes) {
1986
+ return null;
1987
+ }
1988
+
1989
+ return schema.complexTypes[name];
1990
+ };
1991
+
1992
+ WSDL.prototype.findChildSchemaObject = function(parameterTypeObj, childName, backtrace) {
1993
+ if (!parameterTypeObj || !childName) {
1994
+ return null;
1995
+ }
1996
+
1997
+ if (!backtrace) {
1998
+ backtrace = [];
1999
+ }
2000
+
2001
+ if (backtrace.indexOf(parameterTypeObj) >= 0) {
2002
+ // We've recursed back to ourselves; break.
2003
+ return null;
2004
+ } else {
2005
+ backtrace = backtrace.concat([parameterTypeObj]);
2006
+ }
2007
+
2008
+ var found = null,
2009
+ i = 0,
2010
+ child,
2011
+ ref;
2012
+
2013
+ if (Array.isArray(parameterTypeObj.$lookupTypes) && parameterTypeObj.$lookupTypes.length) {
2014
+ var types = parameterTypeObj.$lookupTypes;
2015
+
2016
+ for(i = 0; i < types.length; i++) {
2017
+ var typeObj = types[i];
2018
+
2019
+ if(typeObj.$name === childName) {
2020
+ found = typeObj;
2021
+ break;
2022
+ }
2023
+ }
2024
+ }
2025
+
2026
+ var object = parameterTypeObj;
2027
+ if (object.$name === childName && object.name === 'element') {
2028
+ return object;
2029
+ }
2030
+ if (object.$ref) {
2031
+ ref = splitQName(object.$ref);
2032
+ if (ref.name === childName) {
2033
+ return object;
2034
+ }
2035
+ }
2036
+
2037
+ var childNsURI;
2038
+
2039
+ // want to avoid unecessary recursion to improve performance
2040
+ if (object.$type && backtrace.length === 1) {
2041
+ var typeInfo = splitQName(object.$type);
2042
+ if (typeInfo.prefix === TNS_PREFIX) {
2043
+ childNsURI = parameterTypeObj.$targetNamespace;
2044
+ } else {
2045
+ childNsURI = this.definitions.xmlns[typeInfo.prefix];
2046
+ }
2047
+ var typeDef = this.findSchemaType(typeInfo.name, childNsURI);
2048
+ if (typeDef) {
2049
+ return this.findChildSchemaObject(typeDef, childName, backtrace);
2050
+ }
2051
+ }
2052
+
2053
+ if (object.children) {
2054
+ for (i = 0, child; child = object.children[i]; i++) {
2055
+ found = this.findChildSchemaObject(child, childName, backtrace);
2056
+ if (found) {
2057
+ break;
2058
+ }
2059
+
2060
+ if (child.$base) {
2061
+ var baseQName = splitQName(child.$base);
2062
+ var childNameSpace = baseQName.prefix === TNS_PREFIX ? '' : baseQName.prefix;
2063
+ childNsURI = child.xmlns[baseQName.prefix] || this.definitions.xmlns[baseQName.prefix];
2064
+
2065
+ var foundBase = this.findSchemaType(baseQName.name, childNsURI);
2066
+
2067
+ if (foundBase) {
2068
+ found = this.findChildSchemaObject(foundBase, childName, backtrace);
2069
+
2070
+ if (found) {
2071
+ found.$baseNameSpace = childNameSpace;
2072
+ found.$type = childNameSpace + ':' + childName;
2073
+ break;
2074
+ }
2075
+ }
2076
+ }
2077
+ }
2078
+
2079
+ }
2080
+
2081
+ if (!found && object.$name === childName) {
2082
+ return object;
2083
+ }
2084
+
2085
+ return found;
2086
+ };
2087
+
2088
+ WSDL.prototype._parse = function(xml) {
2089
+ var self = this,
2090
+ p = sax.parser(true),
2091
+ stack = [],
2092
+ root = null,
2093
+ types = null,
2094
+ schema = null,
2095
+ options = self.options;
2096
+
2097
+ p.onopentag = function(node) {
2098
+ var nsName = node.name;
2099
+ var attrs = node.attributes;
2100
+
2101
+ var top = stack[stack.length - 1];
2102
+ var name;
2103
+ if (top) {
2104
+ try {
2105
+ top.startElement(stack, nsName, attrs, options);
2106
+ } catch (e) {
2107
+ if (self.options.strict) {
2108
+ throw e;
2109
+ } else {
2110
+ stack.push(new Element(nsName, attrs, options));
2111
+ }
2112
+ }
2113
+ } else {
2114
+ name = splitQName(nsName).name;
2115
+ if (name === 'definitions') {
2116
+ root = new DefinitionsElement(nsName, attrs, options);
2117
+ stack.push(root);
2118
+ } else if (name === 'schema') {
2119
+ // Shim a structure in here to allow the proper objects to be created when merging back.
2120
+ root = new DefinitionsElement('definitions', {}, {});
2121
+ types = new TypesElement('types', {}, {});
2122
+ schema = new SchemaElement(nsName, attrs, options);
2123
+ types.addChild(schema);
2124
+ root.addChild(types);
2125
+ stack.push(schema);
2126
+ } else {
2127
+ throw new Error('Unexpected root element of WSDL or include');
2128
+ }
2129
+ }
2130
+ };
2131
+
2132
+ p.onclosetag = function(name) {
2133
+ var top = stack[stack.length - 1];
2134
+ assert(top, 'Unmatched close tag: ' + name);
2135
+
2136
+ top.endElement(stack, name);
2137
+ };
2138
+
2139
+ p.write(xml).close();
2140
+
2141
+ return root;
2142
+ };
2143
+
2144
+ WSDL.prototype._fromXML = function(xml) {
2145
+ this.definitions = this._parse(xml);
2146
+ this.definitions.descriptions = {
2147
+ types:{}
2148
+ };
2149
+ this.xml = xml;
2150
+ };
2151
+
2152
+ WSDL.prototype._fromServices = function(services) {
2153
+
2154
+ };
2155
+
2156
+
2157
+
2158
+ WSDL.prototype._xmlnsMap = function() {
2159
+ var xmlns = this.definitions.xmlns;
2160
+ var str = '';
2161
+ for (var alias in xmlns) {
2162
+ if (alias === '' || alias === TNS_PREFIX) {
2163
+ continue;
2164
+ }
2165
+ var ns = xmlns[alias];
2166
+ switch (ns) {
2167
+ case "http://xml.apache.org/xml-soap" : // apachesoap
2168
+ case "http://schemas.xmlsoap.org/wsdl/" : // wsdl
2169
+ case "http://schemas.xmlsoap.org/wsdl/soap/" : // wsdlsoap
2170
+ case "http://schemas.xmlsoap.org/wsdl/soap12/": // wsdlsoap12
2171
+ case "http://schemas.xmlsoap.org/soap/encoding/" : // soapenc
2172
+ case "http://www.w3.org/2001/XMLSchema" : // xsd
2173
+ continue;
2174
+ }
2175
+ if (~ns.indexOf('http://schemas.xmlsoap.org/')) {
2176
+ continue;
2177
+ }
2178
+ if (~ns.indexOf('http://www.w3.org/')) {
2179
+ continue;
2180
+ }
2181
+ if (~ns.indexOf('http://xml.apache.org/')) {
2182
+ continue;
2183
+ }
2184
+ str += ' xmlns:' + alias + '="' + ns + '"';
2185
+ }
2186
+ return str;
2187
+ };
2188
+
2189
+ /*
2190
+ * Have another function to load previous WSDLs as we
2191
+ * don't want this to be invoked externally (expect for tests)
2192
+ * This will attempt to fix circular dependencies with XSD files,
2193
+ * Given
2194
+ * - file.wsdl
2195
+ * - xs:import namespace="A" schemaLocation: A.xsd
2196
+ * - A.xsd
2197
+ * - xs:import namespace="B" schemaLocation: B.xsd
2198
+ * - B.xsd
2199
+ * - xs:import namespace="A" schemaLocation: A.xsd
2200
+ * file.wsdl will start loading, import A, then A will import B, which will then import A
2201
+ * Because A has already started to load previously it will be returned right away and
2202
+ * have an internal circular reference
2203
+ * B would then complete loading, then A, then file.wsdl
2204
+ * By the time file A starts processing its includes its definitions will be already loaded,
2205
+ * this is the only thing that B will depend on when "opening" A
2206
+ */
2207
+ function open_wsdl_recursive(uri, options, callback) {
2208
+ var fromCache,
2209
+ WSDL_CACHE;
2210
+
2211
+ if (typeof options === 'function') {
2212
+ callback = options;
2213
+ options = {};
2214
+ }
2215
+
2216
+ WSDL_CACHE = options.WSDL_CACHE;
2217
+
2218
+ if (fromCache = WSDL_CACHE[ uri ]) {
2219
+ return callback.call(fromCache, null, fromCache);
2220
+ }
2221
+
2222
+ return open_wsdl(uri, options, callback);
2223
+ }
2224
+
2225
+ function open_wsdl(uri, options, callback) {
2226
+ if (typeof options === 'function') {
2227
+ callback = options;
2228
+ options = {};
2229
+ }
2230
+
2231
+ // initialize cache when calling open_wsdl directly
2232
+ var WSDL_CACHE = options.WSDL_CACHE || {};
2233
+ var request_headers = options.wsdl_headers;
2234
+ var request_options = options.wsdl_options;
2235
+
2236
+ var wsdl;
2237
+ if (!/^https?:/.test(uri)) {
2238
+ debug('Reading file: %s', uri);
2239
+ fs.readFile(uri, 'utf8', function(err, definition) {
2240
+ if (err) {
2241
+ callback(err);
2242
+ }
2243
+ else {
2244
+ wsdl = new WSDL(definition, uri, options);
2245
+ WSDL_CACHE[ uri ] = wsdl;
2246
+ wsdl.WSDL_CACHE = WSDL_CACHE;
2247
+ wsdl.onReady(callback);
2248
+ }
2249
+ });
2250
+ }
2251
+ else {
2252
+ debug('Reading url: %s', uri);
2253
+ var httpClient = options.httpClient || new HttpClient(options);
2254
+ httpClient.request(uri, null /* options */, function(err, response, definition) {
2255
+ if (err) {
2256
+ callback(err);
2257
+ } else if (response && response.statusCode === 200) {
2258
+ wsdl = new WSDL(definition, uri, options);
2259
+ WSDL_CACHE[ uri ] = wsdl;
2260
+ wsdl.WSDL_CACHE = WSDL_CACHE;
2261
+ wsdl.onReady(callback);
2262
+ } else {
2263
+ callback(new Error('Invalid WSDL URL: ' + uri + "\n\n\r Code: " + response.statusCode + "\n\n\r Response Body: " + response.body));
2264
+ }
2265
+ }, request_headers, request_options);
2266
+ }
2267
+
2268
+ return wsdl;
2269
+ }
2270
+
2271
+ exports.open_wsdl = open_wsdl;
2272
+ exports.WSDL = WSDL;