Skip to content

Commit

Permalink
feat: allow ComplexContentElement to have a restriction as child elem…
Browse files Browse the repository at this point in the history
…ent and implement attributes parsing for RestrictionElement
  • Loading branch information
TheDadi committed Sep 2, 2024
1 parent d23bdfa commit 95adb37
Show file tree
Hide file tree
Showing 3 changed files with 127 additions and 6 deletions.
33 changes: 27 additions & 6 deletions src/wsdl/elements.ts
Original file line number Diff line number Diff line change
Expand Up @@ -383,18 +383,32 @@ export class RestrictionElement extends Element {
'choice',
'enumeration',
'sequence',
'attribute',
]);
public $base: string;

public description(definitions?: DefinitionsElement, xmlns?: IXmlNs) {
const children = this.children;
let desc;
for (let i = 0, child; child = children[i]; i++) {
if (child instanceof SequenceElement || child instanceof ChoiceElement) {
let isFirstChild = false;
const $attributes = {};

for (const child of children) {
if (child instanceof AttributeElement) {
$attributes[child.$name] = child.description(definitions);
continue;
}
if (!isFirstChild && (child instanceof SequenceElement || child instanceof ChoiceElement)) {
isFirstChild = true;
desc = child.description(definitions, xmlns);
break;
}
}

if (Object.keys($attributes).length > 0) {
desc = desc ?? {};
desc[AttributeElement.Symbol] = $attributes;
}

if (desc && this.$base) {
const type = splitQName(this.$base);
const typeName = type.name;
Expand All @@ -405,11 +419,16 @@ export class RestrictionElement extends Element {
desc.getBase = () => {
return typeElement.description(definitions, schema.xmlns);
};
if (typeElement) {
const baseDescription = typeElement.description(definitions, schema.xmlns);
if (baseDescription[AttributeElement.Symbol]) {
_.defaults($attributes, baseDescription[AttributeElement.Symbol]);
}
desc = _.defaults(desc, baseDescription);
}
return desc;
}

// then simple element
const base = this.$base ? this.$base + '|' : '';
const restrictions = this.children.map((child) => {
return child.description();
}).join(',');
Expand Down Expand Up @@ -525,10 +544,12 @@ export class ComplexTypeElement extends Element {
export class ComplexContentElement extends Element {
public readonly allowedChildren = buildAllowedChildren([
'extension',
'restriction',
]);

public description(definitions: DefinitionsElement, xmlns: IXmlNs) {
for (const child of this.children) {
if (child instanceof ExtensionElement) {
if (child instanceof ExtensionElement || child instanceof RestrictionElement) {
return child.description(definitions, xmlns);
}
}
Expand Down
15 changes: 15 additions & 0 deletions test/wsdl-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -370,4 +370,19 @@ describe('WSDL Parser (non-strict)', () => {
done();
});
});

it('Should describe return correct result for attributes in complexTypeElement with restrictions', function(done) {
soap.createClient(__dirname+ '/wsdl/wsdl_with_restriction_attributes.wsdl', function(err,client){
assert.ifError(err);
var description = client.describe();
assert.deepStrictEqual(description.SampleService.SamplePort.GetPerson.output.ObjectDetails[elements.AttributeElement.Symbol], {
id: { type: 'xsd:string', required: true },
type: { type: 'xsd:long', required: true },
internalName: { type: 'xsd:string', required: false },
key: { type: 'xsd:string', required: false },
origin: { type: 'xsd:string', required: false }
});
done();
});
});
});
85 changes: 85 additions & 0 deletions test/wsdl/wsdl_with_restriction_attributes.wsdl
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns="http://schemas.xmlsoap.org/wsdl/"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:tns="http://example.com/wsdl"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://example.com/wsdl"
name="SampleService">

<types>
<xsd:schema targetNamespace="http://example.com/wsdl">

<xsd:simpleType name="Age">
<xsd:restriction base="xsd:int">
<xsd:minInclusive value="0"/>
<xsd:maxInclusive value="120"/>
</xsd:restriction>
</xsd:simpleType>

<xsd:complexType name="objectKey">
<xsd:sequence/>
<xsd:attribute name="id" type="xsd:string"/>
<xsd:attribute name="internalName" type="xsd:string"/>
<xsd:attribute name="key" type="xsd:string"/>
<xsd:attribute name="type" type="xsd:long" use="required"/>
<xsd:attribute name="origin" type="xsd:string"/>
</xsd:complexType>

<xsd:complexType name="objectDef">
<xsd:complexContent>
<xsd:restriction base="tns:objectKey">
<xsd:attribute name="id" type="xsd:string" use="required"/>
<xsd:attribute fixed="-500020" name="type" type="xsd:long" use="required"/>
</xsd:restriction>
</xsd:complexContent>
</xsd:complexType>

<xsd:complexType name="Person">
<xsd:sequence>
<xsd:element name="Name" type="xsd:string"/>
<xsd:element name="Age" type="tns:Age"/>
<xsd:element name="ObjectDetails" type="tns:objectDef"/>
</xsd:sequence>
<xsd:attribute name="id" type="xsd:string" use="required"/>
</xsd:complexType>

<xsd:element name="Person" type="tns:Person"/>

</xsd:schema>
</types>

<message name="GetPersonRequest">
<part name="personId" type="xsd:string"/>
</message>

<message name="GetPersonResponse">
<part name="Person" element="tns:Person"/>
</message>

<portType name="SamplePortType">
<operation name="GetPerson">
<input message="tns:GetPersonRequest"/>
<output message="tns:GetPersonResponse"/>
</operation>
</portType>

<binding name="SampleBinding" type="tns:SamplePortType">
<soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document"/>
<operation name="GetPerson">
<soap:operation soapAction="http://example.com/wsdl/GetPerson" style="document"/>
<input>
<soap:body use="literal"/>
</input>
<output>
<soap:body use="literal"/>
</output>
</operation>
</binding>

<service name="SampleService">
<port name="SamplePort" binding="tns:SampleBinding">
<soap:address location="http://example.com/SampleService"/>
</port>
</service>

</definitions>

0 comments on commit 95adb37

Please sign in to comment.