Search code examples
c++xsdxsd.execodesynthesis

XSD : How to set attributes values in children element type?


In an xsd file I have this element base type :

<xs:complexType name="event" abstract="true" >
    <xs:attribute name="move" type="aos:move_ref" use="required" />
    <xs:attribute name="type" type="aos:event_type" use="required" />
</xs:complexType>

And I want to define the value of the type attribute in the children types, so I tried this :

<xs:complexType name="signal" >
    <xs:complexContent>
      <xs:extension base="aos:event">
        <xs:attribute name="type" type="aos:event_type" fixed="signal" />
        <xs:attribute name="source" type="aos:signal_source" use="required" />
      </xs:extension>
    </xs:complexContent>
 </xs:complexType>

Visual Studio don't seem to bother but CodeSynthesis C++ code generator don't seem to agree :

error: attribute 'type' is already defined in base

How should I write this? I just want the value of the type attribute to be specific to each different child type.

edit ----

To make the question more clear, I'll write the same thing I want to do but in C++.

Here is the base class :

class Event
{
public:

   std::string name() const { return m_name; }

protected:

   // we need the child class to set the name
   Event( const std::string& name ) : m_name( name ) {} 

   // it's a base class
   virtual ~Event(){}

private:

   std::string m_name;

};

Now, one of the children could be implemented like this :

class Signal : public Event
{
public:

   Signal() : Event( "signal" ){}

};

As you can see, the child class define the values of attributes that are defined by the base class. Is it even possible to express in xsd?


Solution

  • To derive a type and fix a value, use a restriction:

    <xs:complexType name="signal" >
        <xs:complexContent>
          <xs:restriction base="aos:event">
            <xs:attribute name="type" type="aos:event_type" fixed="signal" use="required" />
            <xs:attribute name="source" type="aos:signal_source" use="required" />
          </xs:restriction>
        </xs:complexContent>
     </xs:complexType>
    

    From reading the spec, I would have expected that you couldn't add attributes in a restriction unless the base type had an attribute wildcard, but the W3C XSD validator accepts the above. If you run into problems, you can break up the definition into a restriction and an extension:

    <xs:complexType name="fixedSignalEvent">
      <xs:complexContent>
        <xs:restriction base="aos:event">
          <xs:attribute name="type" type="aos:event_type" fixed="signal" use="required" />
        </xs:restriction>
      </xs:complexContent>
    </xs:complexType>
    
    <xs:complexType name="signal" >
      <xs:complexContent>
        <xs:extension base="aos:fixedSignalEvent">
          <xs:attribute name="source" type="aos:signal_source" use="required" />
        </xs:extension>
      </xs:complexContent>
    </xs:complexType>
    

    Another fix would be to add an attribute wildcard to the base type.

    <xs:complexType name="event" abstract="true" >
        <xs:attribute name="move" type="aos:move_ref" use="required" />
        <xs:attribute name="type" type="aos:event_type" use="required" />
        <xs:anyAttribute />
    </xs:complexType>
    

    This isn't an equivalent solution, as it allows an event to have anything for an attribute (which may be undesirable, generally speaking, but perhaps not for code generation), and it doesn't add an additional type (which is desirable).

    Note that any particles (elements, groups or wildcards) in the base must be repeated in the restriction, else they won't be allowed in the element. If a restricted attribute is required on the base, it must also be required in the restriction. There are numerous other properties a restriction must fulfill to be a valid derivation or particle. The spec isn't that readable, but you can usually stumble through it.

    See also: "how to use restrictions and extensions in XSD simultanously".