{#
Non-empty iff any attribute is serialized as an XML child element (truthy for {% if %}).
#}
{%- macro has_elements(attributes) -%}
{%- for attribute in attributes -%}
{%- if attribute.xml.is_attr is false -%}x{%- endif -%}
{%- endfor -%}
{%- endmacro -%}
{#
use="required" on xs:attribute (mutually exclusive with default in XSD 1.0).
#}
{%- macro is_required(attribute) -%}
{%- if attribute.required is true %} use="required"{%- endif -%}
{%- endmacro -%}
{#
default= only when optional; required attributes cannot carry default per XSD 1.0.
#}
{%- macro get_default(attr) -%}
{%- if 'default' in attr and attr.required is not true %} default="{{ xml_escape(attr.default) }}"{%- endif -%}
{%- endmacro -%}
{#
Cardinality for repeatable elements (optional 0..* vs required 1..*).
#}
{%- macro is_multiple(attribute) -%}
{%- if attribute.multiple is true -%}
{%- if attribute.required is true %} minOccurs="1" maxOccurs="unbounded"{%- else %} minOccurs="0" maxOccurs="unbounded"{%- endif -%}
{%- endif -%}
{%- endmacro -%}
{#
Attribute/element base type: user-defined vs xs: built-in.
#}
{%- macro is_reference(attribute) -%}
{%- if attribute.dtypes[0] in object_names or attribute.dtypes[0] in enum_names -%}
{{ attribute.dtypes[0] }}Type
{%- else -%}
xs:{{ attribute.dtypes[0] }}
{%- endif -%}
{%- endmacro -%}
{%- macro create_attribute(attribute) -%}
{%- if attribute.docstring | length > 0 %}
<xs:attribute name="{{ attribute.name }}" type="{{ is_reference(attribute) }}"
{%- if is_required(attribute) %} {{ is_required(attribute) }}{%- endif -%}
{%- if get_default(attribute) %} {{ get_default(attribute) }}{%- endif -%}
>
<xs:annotation>
<xs:documentation>
{{ wrap(xml_escape(attribute.docstring), 70, "", " ", None) }}
</xs:documentation>
</xs:annotation>
</xs:attribute>
{%- else -%}
<xs:attribute name="{{ attribute.name }}" type="{{ is_reference(attribute) }}"
{%- if is_required(attribute) %} {{ is_required(attribute) }}{%- endif -%}
{%- if get_default(attribute) %} {{ get_default(attribute) }}{%- endif -%}
/>
{%- endif -%}
{%- endmacro %}
{%- macro create_element(attribute) -%}
{%- if attribute.dtypes[0] in object_names or attribute.dtypes[0] in enum_names -%}
{%- if attribute.multiple is true -%}
<xs:element name="{{attribute.name}}">
{%- if attribute.docstring | length > 0 %}
<xs:annotation>
<xs:documentation>
{{ wrap(xml_escape(attribute.docstring), 70, "", " ", None) }}
</xs:documentation>
</xs:annotation>
{%- endif %}
<xs:complexType>
<xs:sequence>
<xs:element name="{{attribute.dtypes[0]}}" type="{{attribute.dtypes[0]}}Type"
{%- if is_multiple(attribute) %}{{ is_multiple(attribute) }}{%- endif -%}
/>
</xs:sequence>
</xs:complexType>
</xs:element>
{%- else -%}
{%- if attribute.docstring | length > 0 -%}
<xs:element name="{{attribute.name}}" type="{{attribute.dtypes[0]}}Type">
<xs:annotation>
<xs:documentation>
{{ wrap(xml_escape(attribute.docstring), 70, "", " ", None) }}
</xs:documentation>
</xs:annotation>
</xs:element>
{%- else -%}
<xs:element name="{{attribute.name}}" type="{{attribute.dtypes[0]}}Type"/>
{%- endif -%}
{%- endif -%}
{%- else -%}
{%- if attribute.docstring | length > 0 -%}
<xs:element name="{{attribute.name}}" type="xs:{{attribute.dtypes[0]}}"
{%- if is_multiple(attribute) %} {{ is_multiple(attribute) }}{% endif -%}
{%- if get_default(attribute) %} {{ get_default(attribute) }}{% endif -%}
>
<xs:annotation>
<xs:documentation>
{{ wrap(xml_escape(attribute.docstring), 70, "", " ", None) }}
</xs:documentation>
</xs:annotation>
</xs:element>
{%- else -%}
<xs:element name="{{attribute.name}}" type="xs:{{attribute.dtypes[0]}}"
{%- if is_multiple(attribute) %} {{ is_multiple(attribute) }}{%- endif %}
{%- if get_default(attribute) %} {{ get_default(attribute) }}{%- endif -%}
/>
{%- endif -%}
{%- endif -%}
{%- endmacro %}
<?xml version="1.0" encoding="UTF-8" ?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
{%- for object in object_names %}
<xs:element name="{{ object }}" type="{{ object }}Type"/>
{%- endfor %}
{% for object in objects%}
<xs:complexType name="{{ object.name }}Type">
{%- if has_elements(object.attributes) %}
<xs:sequence>
{%- for attribute in object.attributes %}
{%- if attribute.xml.is_attr is false %}
{{ create_element(attribute) }}
{%- endif %}
{%- endfor %}
</xs:sequence>
{%- endif -%}
{%- for attribute in object.attributes -%}
{%- if attribute.xml.is_attr is true -%}
{{ create_attribute(attribute) }}
{%- endif -%}
{%- endfor %}
</xs:complexType>
{% endfor %}
{%- for enum in enums %}
<xs:simpleType name="{{ enum.name }}Type">
<xs:restriction base="xs:string">
{%- for key, value in enum.mappings | dictsort %}
<xs:enumeration value="{{ xml_escape(value) }}"/>
{%- endfor %}
</xs:restriction>
</xs:simpleType>
{%- endfor %}
</xs:schema>