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

Jan Klimke jan.klimke at hpi.uni-potsdam.de
Thu Sep 25 13:25:19 EDT 2008


Thank you for your detailed answer. Unfortunately i did not have time to
try it until today. THe customization works fine. I am able to specify
the name of the binarycomaprison element.

But one big problem remains. I am currently doing the following in my code:
      schemas::coll::Boolean& b = schemas::coll::Boolean(true);
      xml_schema::string& name = xml_schema::string("coll:isActive");
      ogc::LiteralType& lit = (ogc::LiteralType&)b;
      ogc::PropertyNameType& pname = (ogc::PropertyNameType&)name;

      ogc::BinaryComparisonOpType& isEqualActive =
ogc::BinaryComparisonOpType();
      ogc::BinaryComparisonOpType::expression_sequence& expressions =
        ogc::BinaryComparisonOpType::expression_sequence();

      expressions.push_back(pname);
      expressions.push_back(lit);
      isEqualActive.expression(expressions);
     
      filter.comparisonOps(isEqualActive);
      filter.setOpName(std::string("PropertyIsEqualTo"));

When i serialize the filter object the PropertyNameType and Literal
object are serialized as expression elements, but they should be
PropertyName and Literal elements to be accepted by the service i plan
to call.

<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<wfs:GetFeature xmlns:wfs="http://www.opengis.net/wfs"
outputFormat="text/xml; subtype=gml/3.1.1" resultType="results"
service="WFS" version="1.1.0"
xmlns:coll="http://www.hpi.uni-potsdam.de/schemas/coll"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.opengis.net/wfs
http://localhost:8080/schemas/wfs.xsd">

  <wfs:Query typeName="coll:CollaborationSession"
xmlns:p1="http://www.opengis.n
et/ogc">
    <p1:Filter>
      <PropertyIsEqualTo xmlns="http://www.opengis.net/ogc"
matchCase="true">
        <p1:expression xmlns:p2="http://www.w3.org/2001/XMLSchema"
xsi:type="p2:string">coll:isActive</p1:expression>
        <p1:expression xsi:type="coll:Boolean">true</p1:expression>
      </PropertyIsEqualTo>
    </p1:Filter>
  </wfs:Query>

</wfs:GetFeature>

So the serialization method from Expression is obviously used. What am i
doing wrong ? Did i miss something ?

Jan

Boris Kolpackov schrieb:
> 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