xuri / xgen

XSD (XML Schema Definition) parser and Go/C/Java/Rust/TypeScript code generator
BSD 3-Clause "New" or "Revised" License
313 stars 74 forks source link

obix xsd breaks xgen #65

Open sruehl opened 1 year ago

sruehl commented 1 year ago

obix xsd breaks xgen

Steps to reproduce the issue:

  1. Use the obix xsd
    
    <?xml version="1.0" encoding="UTF-8"?>
    <!--
     OBIX Version 1.1
     Committee Specification 01
     14 September 2015
     Copyright (c) OASIS Open 2015. All Rights Reserved.
     Source: http://docs.oasis-open.org/obix/obix/v1.1/cs01/schemas/
    -->
    <xs:schema xmlns="http://docs.oasis-open.org/obix/ns/201506" xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="http://docs.oasis-open.org/obix/ns/201506" elementFormDefault="qualified" id="obix">
    <!-- Simple Types
     ===================== -->
    <xs:simpleType name="status">
        <xs:annotation>
            <xs:documentation>The status Facet is used to annotate an Object about the quality and state of the information.</xs:documentation>
        </xs:annotation>
        <xs:restriction base="xs:string">
            <xs:enumeration value="disabled"/>
            <xs:enumeration value="fault"/>
            <xs:enumeration value="down"/>
            <xs:enumeration value="unackedAlarm"/>
            <xs:enumeration value="alarm"/>
            <xs:enumeration value="unacked"/>
            <xs:enumeration value="overridden"/>
            <xs:enumeration value="ok"/>
            <!-- ordered by priority -->
        </xs:restriction>
    </xs:simpleType>
    <xs:simpleType name="contractList">
        <xs:annotation>
            <xs:documentation> A sequence of Contracts referenced by an OBIX Object describing the Contracts which the Object implements. A Contract is a template, defined as an OBIX Object, that is referenced by other Objects by using the URI to the Contract Definition. Each Contract Elements is a URI. In XSD, it is a string because the collection of URIs follows special serialization rules, i.e., URIs are space separated, and the zero length list is specified as "nil", See the specification for details.</xs:documentation>
        </xs:annotation>
        <xs:restriction base="xs:string"/>
    </xs:simpleType>
    <!-- Complex Types
     ===================== -->
    <xs:complexType name="Obj">
        <xs:annotation>
            <xs:documentation>Obj is the common base Object type, from which the other object types are derived.</xs:documentation>
        </xs:annotation>
        <xs:sequence>
            <xs:element ref="obj" minOccurs="0" maxOccurs="unbounded"/>
            <!-- Note to Reviewers:
                The element below was defined in 1.0 and is now removed.
                See note above for details. We recommend new development use namespaces instead.
            <xs:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
            -->
        </xs:sequence>
        <xs:attribute ref="display"/>
        <xs:attribute ref="displayName"/>
        <xs:attribute ref="href"/>
        <xs:attribute ref="icon"/>
        <xs:attribute ref="is"/>
        <xs:attribute ref="name"/>
        <xs:attribute ref="null"/>
        <xs:attribute ref="status" default="ok"/>
        <xs:attribute ref="ts"/>
        <xs:attribute ref="writable" default="false"/>
    </xs:complexType>
    <xs:complexType name="AbsTime">
        <xs:annotation>
            <xs:documentation>The abstime type is used to represent an absolute point in time. Its val attribute maps to xs:dateTime, with the exception that it MUST contain the timezone.</xs:documentation>
        </xs:annotation>
        <xs:complexContent>
            <xs:extension base="Obj">
                <xs:attribute name="min" type="xs:dateTime"/>
                <xs:attribute name="max" type="xs:dateTime"/>
                <xs:attribute name="val" type="xs:dateTime"/>
                <xs:attribute ref="tz"/>
            </xs:extension>
            <!-- obix 1.1 -->
        </xs:complexContent>
    </xs:complexType>
    <xs:complexType name="Bool">
        <xs:complexContent>
            <xs:extension base="Obj">
                <xs:attribute ref="range"/>
                <xs:attribute name="val" type="xs:boolean" default="false"/>
            </xs:extension>
        </xs:complexContent>
    </xs:complexType>
    <xs:complexType name="Err">
        <xs:complexContent>
            <xs:extension base="Obj"/>
        </xs:complexContent>
    </xs:complexType>
    <xs:complexType name="Enum">
        <xs:annotation>
            <xs:documentation>The enum type is used to represent a value which must match a finite set of values.</xs:documentation>
        </xs:annotation>
        <xs:complexContent>
            <xs:extension base="Obj">
                <xs:attribute ref="range"/>
                <xs:attribute name="val" type="xs:NMTOKEN"/>
            </xs:extension>
        </xs:complexContent>
    </xs:complexType>
    <xs:complexType name="Feed">
        <xs:annotation>
            <xs:documentation>The feed type is used to define a topic for a Feed of events. Feeds are used with Watches to subscribe to a stream of events such as alarms.</xs:documentation>
        </xs:annotation>
        <xs:complexContent>
            <xs:extension base="Obj">
                <xs:attribute ref="in" default="obix:Nil"/>
                <xs:attribute ref="of" default="obix:obj"/>
            </xs:extension>
        </xs:complexContent>
    </xs:complexType>
    <xs:complexType name="Int">
        <xs:complexContent>
            <xs:extension base="Obj">
                <xs:attribute name="min" type="xs:long"/>
                <xs:attribute name="max" type="xs:long"/>
                <xs:attribute ref="unit"/>
                <xs:attribute name="val" type="xs:long" default="0"/>
            </xs:extension>
        </xs:complexContent>
    </xs:complexType>
    <xs:complexType name="List">
        <xs:annotation>
            <xs:documentation>The list type is a specialized Object type for storing a list of other Objects.</xs:documentation>
        </xs:annotation>
        <xs:complexContent>
            <xs:extension base="Obj">
                <xs:attribute name="min" type="xs:long"/>
                <xs:attribute name="max" type="xs:long"/>
                <xs:attribute ref="of" default="obix:obj"/>
            </xs:extension>
        </xs:complexContent>
    </xs:complexType>
    <xs:complexType name="Op">
        <xs:annotation>
            <xs:documentation>The op type is used to define an operation. All operations take one input Object as a parameter, and return one Object as an output. The input and output Contracts are defined via the in and out attributes.</xs:documentation>
        </xs:annotation>
        <xs:complexContent>
            <xs:extension base="Obj">
                <xs:attribute ref="in" default="obix:Nil"/>
                <xs:attribute ref="out" default="obix:Nil"/>
            </xs:extension>
        </xs:complexContent>
    </xs:complexType>
    <xs:complexType name="Real">
        <xs:complexContent>
            <xs:extension base="Obj">
                <xs:attribute name="min" type="xs:double"/>
                <xs:attribute name="max" type="xs:double"/>
                <xs:attribute ref="precision"/>
                <xs:attribute ref="unit"/>
                <xs:attribute name="val" type="xs:double" default="0"/>
            </xs:extension>
        </xs:complexContent>
    </xs:complexType>
    <xs:complexType name="Ref">
        <xs:annotation>
            <xs:documentation>The ref type is used to create an external reference to another OBIX Object.</xs:documentation>
        </xs:annotation>
        <xs:complexContent>
            <xs:extension base="Obj"/>
        </xs:complexContent>
    </xs:complexType>
    <xs:complexType name="RelTime">
        <xs:annotation>
            <xs:documentation>The reltime type is used to represent a relative duration of time.</xs:documentation>
        </xs:annotation>
        <xs:complexContent>
            <xs:extension base="Obj">
                <xs:attribute name="min" type="xs:duration"/>
                <xs:attribute name="max" type="xs:duration"/>
                <xs:attribute name="val" type="xs:duration" default="PT0S"/>
            </xs:extension>
            <!-- obix 1.1 -->
        </xs:complexContent>
    </xs:complexType>
    <xs:complexType name="Str">
        <xs:complexContent>
            <xs:extension base="Obj">
                <xs:attribute name="min" type="xs:long"/>
                <xs:attribute name="max" type="xs:long"/>
                <xs:attribute name="val" type="xs:string" default=""/>
            </xs:extension>
        </xs:complexContent>
    </xs:complexType>
    <xs:complexType name="Uri">
        <xs:complexContent>
            <xs:extension base="Obj">
                <xs:attribute name="val" type="xs:anyURI"/>
            </xs:extension>
        </xs:complexContent>
    </xs:complexType>
    <!-- obix 1.1 -->
    <xs:complexType name="Date">
        <xs:complexContent>
            <xs:extension base="Obj">
                <xs:attribute name="min" type="xs:date"/>
                <xs:attribute name="max" type="xs:date"/>
                <xs:attribute name="val" type="xs:date"/>
            </xs:extension>
        </xs:complexContent>
    </xs:complexType>
    <xs:complexType name="Time">
        <xs:complexContent>
            <xs:extension base="Obj">
                <xs:attribute name="min" type="xs:time"/>
                <xs:attribute name="max" type="xs:time"/>
                <xs:attribute name="val" type="xs:time"/>
            </xs:extension>
        </xs:complexContent>
    </xs:complexType>
    <!-- Global Attributes
     ===================== -->
    <xs:attribute name="display" type="xs:string">
        <xs:annotation>
            <xs:documentation>provides a localized human readable description of the Object</xs:documentation>
        </xs:annotation>
    </xs:attribute>
    <xs:attribute name="displayName" type="xs:string">
        <xs:annotation>
            <xs:documentation>provides a localized human readable name of the Objec</xs:documentation>
        </xs:annotation>
    </xs:attribute>
    <xs:attribute name="href" type="xs:anyURI">
        <xs:annotation>
            <xs:documentation>href of an Obj. If specified, the root Object MUST have an absolute URI. All other hrefs within an obix document are treated as URI references which may be relative.</xs:documentation>
        </xs:annotation>
    </xs:attribute>
    <xs:attribute name="icon" type="xs:anyURI">
        <xs:annotation>
            <xs:documentation>provides a URI reference to a graphical icon which may be used to represent the Object in an user agent</xs:documentation>
        </xs:annotation>
    </xs:attribute>
    <xs:attribute name="in" type="contractList">
        <xs:annotation>
            <xs:documentation>Specifies the input argument type used by this Object.</xs:documentation>
        </xs:annotation>
    </xs:attribute>
    <xs:attribute name="is" type="contractList">
        <xs:annotation>
            <xs:documentation>Names the Contract the Object implements.</xs:documentation>
        </xs:annotation>
    </xs:attribute>
    <xs:attribute name="name" type="xs:NMTOKEN">
        <xs:annotation>
            <xs:documentation/>
        </xs:annotation>
    </xs:attribute>
    <xs:attribute name="null" type="xs:boolean">
        <xs:annotation>
            <xs:documentation>Attribute if True indicates that this Object has no value, has not been configured or initialized, or is otherwise not defined. Null is a boolean</xs:documentation>
        </xs:annotation>
    </xs:attribute>
    <xs:attribute name="of" type="contractList">
        <xs:annotation>
            <xs:documentation>Specifies the type of child Objects contained by this Object.</xs:documentation>
        </xs:annotation>
    </xs:attribute>
    <xs:attribute name="out" type="contractList">
        <xs:annotation>
            <xs:documentation>Specifies the output argument type used by this Object.</xs:documentation>
        </xs:annotation>
    </xs:attribute>
    <xs:attribute name="precision" type="xs:long">
        <xs:annotation>
            <xs:documentation>used to describe the number of decimal places to use for a real value</xs:documentation>
        </xs:annotation>
    </xs:attribute>
    <xs:attribute name="range" type="xs:anyURI">
        <xs:annotation>
            <xs:documentation>used to define the value space of an enumeration. A range attribute is a URI
    reference to an obix:Range Object</xs:documentation>
        </xs:annotation>
    </xs:attribute>
    <xs:attribute name="status" type="status">
        <xs:annotation>
            <xs:documentation>used to annotate an Object about the quality and state of the information. Status is a pre-enumerated value as described in the obix Specification.</xs:documentation>
        </xs:annotation>
    </xs:attribute>
    <xs:attribute name="ts" type="xs:string">
        <xs:annotation>
            <xs:documentation>ts or tagspace applies a defined semantic tag to this object. The semantic tags are defined by the tagspaces as referenced in the Lobby</xs:documentation>
        </xs:annotation>
    </xs:attribute>
    <xs:attribute name="tz" type="xs:string">
        <xs:annotation>
            <xs:documentation>used to annotate an abstime, date, or time Object with a timezone. The value of a tz attribute is a zoneinfo string identifier, as specified in the IANA Time Zone (ZoneInfo DB) database.</xs:documentation>
        </xs:annotation>
    </xs:attribute>
    <xs:attribute name="unit" type="xs:anyURI">
        <xs:annotation>
            <xs:documentation>defines a unit of measurement in the SI Units system.</xs:documentation>
        </xs:annotation>
    </xs:attribute>
    <xs:attribute name="writable" type="xs:boolean">
        <xs:annotation>
            <xs:documentation>specifies if this Object can be written by the client. If false (the default), then the Object is read-only.</xs:documentation>
        </xs:annotation>
    </xs:attribute>
    <!-- Global Elements
     ===================== -->
    <xs:element name="obj" type="Obj">
        <xs:annotation>
            <xs:documentation>conveys an obix Object. The Object is the common base type for the derived types. An Object has  associated properties, called Facets, common to all derived types. </xs:documentation>
        </xs:annotation>
    </xs:element>
    <xs:element name="abstime" type="AbsTime" substitutionGroup="obj">
        <xs:annotation>
            <xs:documentation>conveys a representation of an absolute point in time. AbsTime is an xs:dateTime with a mandatory timezone.</xs:documentation>
        </xs:annotation>
    </xs:element>
    <xs:element name="bool" type="Bool" substitutionGroup="obj">
        <xs:annotation>
            <xs:documentation>conveys a boolean value – true or false</xs:documentation>
        </xs:annotation>
    </xs:element>
    <xs:element name="enum" type="Enum" substitutionGroup="obj">
        <xs:annotation>
            <xs:documentation>conveys an enumerated value within a fixed set of choices</xs:documentation>
        </xs:annotation>
    </xs:element>
    <xs:element name="err" type="Obj" substitutionGroup="obj">
        <xs:annotation>
            <xs:documentation>Conveys an Err Object. Its actual semantics are context dependent. Typically err Objects SHOULD include a human readable description of the problem via the display attribute.</xs:documentation>
        </xs:annotation>
    </xs:element>
    <xs:element name="feed" type="Feed" substitutionGroup="obj">
        <xs:annotation>
            <xs:documentation>Conveys a feed of events. Feeds are used with watches to subscribe to a stream of events such as alarms. Feeds are subscribed via Watches</xs:documentation>
        </xs:annotation>
    </xs:element>
    <xs:element name="int" type="Int" substitutionGroup="obj">
        <xs:annotation>
            <xs:documentation>conveys an integer value</xs:documentation>
        </xs:annotation>
    </xs:element>
    <xs:element name="list" type="List" substitutionGroup="obj">
        <xs:annotation>
            <xs:documentation>conveys a list of other Objects.</xs:documentation>
        </xs:annotation>
    </xs:element>
    <xs:element name="op" type="Op" substitutionGroup="obj">
        <xs:annotation>
            <xs:documentation>conveys an operation (Op) type. All operations take one input Object as a parameter, and return one Object as an output. The input and output Contracts are defined via the in and out attributes.</xs:documentation>
        </xs:annotation>
    </xs:element>
    <xs:element name="real" type="Real" substitutionGroup="obj">
        <xs:annotation>
            <xs:documentation>conveys a floating point value</xs:documentation>
        </xs:annotation>
    </xs:element>
    <xs:element name="ref" type="Ref" substitutionGroup="obj">
        <xs:annotation>
            <xs:documentation>conveys an external reference to another obix Object. It is the obix equivalent of the HTML anchor tag.</xs:documentation>
        </xs:annotation>
    </xs:element>
    <xs:element name="reltime" type="RelTime" substitutionGroup="obj">
        <xs:annotation>
            <xs:documentation>stores a relative time value (duration or time span)</xs:documentation>
        </xs:annotation>
    </xs:element>
    <xs:element name="str" type="Str" substitutionGroup="obj">
        <xs:annotation>
            <xs:documentation>conveys a UNICODE string</xs:documentation>
        </xs:annotation>
    </xs:element>
    <xs:element name="uri" type="Uri" substitutionGroup="obj">
        <xs:annotation>
            <xs:documentation>conveys a Universal Resource Identifier</xs:documentation>
        </xs:annotation>
    </xs:element>
    <!-- obix 1.1 -->
    <xs:element name="date" type="Date" substitutionGroup="obj">
        <xs:annotation>
            <xs:documentation>conveys a specific date as day, month, and year</xs:documentation>
        </xs:annotation>
    </xs:element>
    <xs:element name="time" type="Time" substitutionGroup="obj">
        <xs:annotation>
            <xs:documentation>conveys  a time of day in hours, minutes, and seconds. Time values in MUST omit the timezone offset and MUST NOT use the trailing “Z”</xs:documentation>
        </xs:annotation>
    </xs:element>
    </xs:schema>
2. Run xgen
`~/go/bin/xgen -i obix-v1.1.xsd -o test -l Go`
3. Be puzzled by the generated go code

**Describe the results you received:**
- Elements overwrite struct types
- Elements are defined as a substitution group for obj but are not actually asignable

**Describe the results you expected:**
- compileable code

**Output of `go version`:**

```text
go1.18.1

xgen version or commit ID:

v0.0.0-20221130013449-4b677f0df988