[xsd-users] Specifying Element content for "anyType" Elements

Boris Kolpackov boris at codesynthesis.com
Fri Sep 12 04:21:13 EDT 2008


Hi Jan,

Jan Klimke <jan.klimke at hpi.uni-potsdam.de> writes:

> i tried to create an PropertyIsEqualTo element which is defined as follows:
> 
>  <xsd:element name="PropertyIsEqualTo"
>                 type="ogc:BinaryComparisonOpType"
>                 substitutionGroup="ogc:comparisonOps"/>
>
> [...] 
>
> As you can see, the generated element is not the desired one but
> "PropertyIsGreaterThanOrEqualTo".
> 
> This element is defined like the PropertyIsEqualTo element:
> 
>  <xsd:element name="PropertyIsGreaterThanOrEqualTo"
> type="ogc:BinaryComparisonOpType" substitutionGroup="ogc:comparisonOps"/>
> 
> Because they are both of the same type no other class as
> ogc:BinaryComparisonOpType is generated. 

It looks like this schema is using element names as some sort of
identifiers even though they are all of the same type. This does
not work very well with XSD's automatic handling of substitution
groups since the generated code uses the first element name that
matches the type. I see two ways how you can resolve this:

1. You can change the schema to an equivalent one but which assigns
   different types to different operation elements. This schema will
   be equivalent to the original in the sense that it will define
   the same XML vocabulary:

   <xsd:complexType name="IsEqualToType">
      <xsd:complexContent>
         <xsd:extension base="ogc:BinaryComparisonOpType"/>
      </xsd:complexContent>
   </xsd:complexType>
  
   <xsd:element name="PropertyIsEqualTo"
                type="ogc:IsEqualToType"
                substitutionGroup="ogc:comparisonOps"/>

   <xsd:complexType name="IsGreaterThanOrEqualToType">
      <xsd:complexContent>
         <xsd:extension base="ogc:BinaryComparisonOpType"/>
      </xsd:complexContent>
   </xsd:complexType>

  <xsd:element name="PropertyIsGreaterThanOrEqualTo"
               type="ogc:IsGreaterThanOrEqualToType" 
               substitutionGroup="ogc:comparisonOps"/>

  And so on for all the elements that substitute comparisonOps and are
  of the BinaryComparisonOpType type.

2. The second method is quite a bit more involved but does not require
   any schema modifications. With this method you will need to customize
   all the types that contain the comparisonOps element (e.g., FilterType).
   Your customization will need to do two things:

   a) Add a mechanism for specifying which element name should be used.
      This can be a modifier function that passes element name as a
      string.

   b) Customize the serialization operator to change the name of the
      DOM element.


   For more information on type customization, see the C++/Tree
   Mapping Customization Guide:

   http://wiki.codesynthesis.com/Tree/Customization_guide

   There is also a bunch of examples in the examples/cxx/tree/custom/
   directory with the most relevant to your case being 'wildcard'. 

   Here is an outline of the FilterType implementation. In your case
   you don't need to customize parsing so we just call the base
   implementation (or you can change it to extract the operation
   name from DOM):

   class FilterType: public FilterTypeBase
   {
   public:
     void
     comparisonOpName (const std::string& name)
     {
       comparisonOpName_ = name;
     }

     const std::string&
     comparisonOpName () const
     {
       return comparisonOpName_;
     }

     // Parsing constructor. Just call our base.
     //
     FilterType (const xercesc::DOMElement& e,
                 xml_schema::flags = 0,
                 xml_schema::container* = 0)
       : data_base (e, f, c)
     {
     }

     ...

   private:
     std::string comparisonOpName_;
   };

   // Serialization operator.
   //
   void
   operator<< (xercesc::DOMElement&, const FilterType& f)
   {
     // Use our base to serialize data and id.
     //
     const FilterTypeBase& fb (f);
     e << fb;

     if (f.comparisonOps ().present ())
     {
       // Change the name of the child element of 'e' to the one
       // returned by f.comparisonOpName (). Use the renameNode()
       // function on DOMDocument.
     }
   }

   When you use this type in your code you will need to set the
   actual name of the comparisonOps element manually.


> And also the instance of PropertyNameType and LiteralType where not
> serialized as the elements i wanted.

It is hard to answer this without knowing what you actually wanted ;-).


> The other issue i found was assigning boolean values as a LiteralType
> instance. The does not work because  xml_schema::boolean does not 
> derrive from xml_schema::type.

That's right. Types that are mapped to fundamental C++ types cannot
be used for dynamic typing. What you can do is add a type that derives
from the boolean XML Schema type:

  <xsd:simpleType name="Boolean">
    <xsd:restriction base="xsd:boolean"/>
  </xsd:simpleType>

Then you can use this type since it will be derived from xml_schema::type.

Boris




More information about the xsd-users mailing list