diff --git a/src/schema/Type.ts b/src/schema/Type.ts index fde82ef..2cfc1a0 100644 --- a/src/schema/Type.ts +++ b/src/schema/Type.ts @@ -10,8 +10,9 @@ export class Type { var output: string[] = []; if(this.primitiveList && this.primitiveList.length) { - //TODO: if parent is a string restricted to enumerated alternatives, output them joined with pipe characters. - output.push(this.primitiveList[0]); + if(this.primitiveList.length > 1) { + output.push('(' + this.primitiveList.join(' | ') + ')'); + } else output.push(this.primitiveList[0]); } else { var members = this.exportMembersTS(namespace, indent + '\t', ''); diff --git a/src/xsd/Exporter.ts b/src/xsd/Exporter.ts index 8e6ba9e..be23d54 100644 --- a/src/xsd/Exporter.ts +++ b/src/xsd/Exporter.ts @@ -162,21 +162,33 @@ function exportType(type: types.TypeBase, namespace: schema.Namespace) { var outType = type.getOutType(); outType.comment = comment; - var parent = type.parent; + var parentPrimitive = type.getParent(types.Primitive, true); + + if(parentPrimitive) { + var primitiveList: string[]; + var parentSimple = type.getParent(types.SimpleType, false) as types.SimpleType; - if(parent && parent instanceof types.Primitive) { - // TODO: if parent is a string restricted to enumerated alternatives, output those instead. - outType.primitiveList = [parent.name]; - } else { - if(parent instanceof types.TypeBase) { - outType.parent = parent.getOutType(); - namespace.markUsed(parent.qName.namespace.id); + if(parentSimple) { + // If parent is restricted to enumerated alternatives, output those instead. + primitiveList = parentSimple.getEnumerationList(); + if(primitiveList) primitiveList = primitiveList.map((content: string) => '"' + content + '"'); } - outType.attributeList = exportAttributes(scope, namespace); - outType.childList = exportChildren(scope, namespace); + if(!primitiveList) primitiveList = [parentPrimitive.name]; + + outType.primitiveList = primitiveList; + } + + var parent = type.parent; + + if(parent instanceof types.TypeBase && parent != parentPrimitive) { + outType.parent = parent.getOutType(); + if(parent.qName) namespace.markUsed(parent.qName.namespace.id); } + outType.attributeList = exportAttributes(scope, namespace); + outType.childList = exportChildren(scope, namespace); + return(outType); } diff --git a/src/xsd/Parser.ts b/src/xsd/Parser.ts index c976fff..2105dff 100644 --- a/src/xsd/Parser.ts +++ b/src/xsd/Parser.ts @@ -187,7 +187,11 @@ export class Parser { /** Bind references, call after all imports have been initialized. */ resolve() { try { - this.pendingList.forEach((state: State) => state.xsdElement.resolve(state)); + for(var pos = 0; pos < this.pendingList.length; ++pos) { + var state = this.pendingList[pos]; + state.xsdElement.resolve(state); + } + this.pendingList = []; } catch(err) { console.error(err); diff --git a/src/xsd/Scope.ts b/src/xsd/Scope.ts index 118f09b..73f8f90 100644 --- a/src/xsd/Scope.ts +++ b/src/xsd/Scope.ts @@ -140,6 +140,14 @@ console.log('Missing ' + type + ': ' + name.name); return((this.expose['attribute'] || {}) as {[name: string]: TypeMember}); } + hasAttributes() { + var tbl = this.expose['attribute']; + + for(var key in tbl) if(tbl.hasOwnProperty(key)) return(true); + + return(false); + } + static getPrimitiveScope() { var scope = this.primitiveScope; diff --git a/src/xsd/types/ComplexType.ts b/src/xsd/types/ComplexType.ts index 052c4d4..cec6620 100644 --- a/src/xsd/types/ComplexType.ts +++ b/src/xsd/types/ComplexType.ts @@ -14,6 +14,16 @@ export class SimpleType extends types.TypeBase { List, Union ]; + + setEnumerationList(enumerationList: string[]) { + this.enumerationList = enumerationList; + } + + getEnumerationList() { + return(this.enumerationList); + } + + private enumerationList: string[]; } /** */ diff --git a/src/xsd/types/Enumeration.ts b/src/xsd/types/Enumeration.ts index b6874a8..a589978 100644 --- a/src/xsd/types/Enumeration.ts +++ b/src/xsd/types/Enumeration.ts @@ -12,7 +12,9 @@ export class Enumeration extends types.Base { ]; init(state: State) { - (state.parent.xsdElement as types.Restriction).addEnumeration(this.value); + var parent = state.parent.xsdElement; + + if(parent instanceof types.Restriction) parent.addEnumeration(this.value); } value: string = null; diff --git a/src/xsd/types/Restriction.ts b/src/xsd/types/Restriction.ts index 64cd170..1ddb10e 100644 --- a/src/xsd/types/Restriction.ts +++ b/src/xsd/types/Restriction.ts @@ -13,10 +13,36 @@ export class Restriction extends DerivationBase { types.Enumeration ]); + // TODO: Remove this. + init(state: State) { + this.parent = state.parent; + } + +/* + TODO: uncomment this when resolve function dependencies are handled. + resolve(state: State) { + var parent = state.parent.xsdElement; + + if(parent instanceof types.SimpleType) { + parent.setEnumerationList(this.enumerationList); + } + } +*/ + addEnumeration(content: string) { - if(!this.enumerationList) this.enumerationList = []; + if(!this.enumerationList) { + this.enumerationList = []; + + // TODO: Remove this and uncomment the resolve function. + var parent = this.parent.xsdElement; + + if(parent instanceof types.SimpleType) { + parent.setEnumerationList(this.enumerationList); + } + } this.enumerationList.push(content); } - enumerationList: string[]; + private parent: State; // TODO: Remove this. + private enumerationList: string[]; } diff --git a/src/xsd/types/TypeBase.ts b/src/xsd/types/TypeBase.ts index 6364a8d..d81f420 100644 --- a/src/xsd/types/TypeBase.ts +++ b/src/xsd/types/TypeBase.ts @@ -1,7 +1,7 @@ // This file is part of fast-xml, copyright (c) 2015-2016 BusFaster Ltd. // Released under the MIT license, see LICENSE. -import {Base} from './Base'; +import {Base, BaseClass} from './Base'; import {State} from '../State'; import {QName} from '../QName'; import * as schema from '../../schema'; @@ -33,6 +33,26 @@ export class TypeBase extends Base { return(outType); } + /** Find parent type inheriting from a base type. */ + + getParent(base: BaseClass, breakAtContent: boolean) { + var next: TypeBase | QName = this; + var type: TypeBase | QName; + /** Maximum iterations in case type inheritance forms a loop. */ + var iter = 100; + + while(--iter) { + type = next; + + if(!(type instanceof TypeBase)) break; + else if(type instanceof base) return(type); + else if(breakAtContent && type.scope && type.scope.hasAttributes()) break; + else next = type.parent; + } + + return(null); + } + id: string = null; name: string = null;