[xsd-users] CityGML deserialization - <cityObjectMember> tag [Corrected]

Adrian Victor Manoliu victor.manoliu at yahoo.com
Wed Apr 20 03:54:23 EDT 2011



Hello,

After a long pause I've returned to my CityGML project and everything started to 
make sense quicker than I expected. Thank you for your help, it helped me 
realise which way to go. To sum up what I've written below (in case you don't 
have the time to read everything), the CityGML serialization works, however one 
tag is not generated properly - <cityObjectMember> is always replaced by 
<gml:featureMember>, perhaps a problem caused by substitution groups.

First, a brief reminder on how to actually serialize CityGML tags. It took me 
some time to understand the CityGML schema hierarchies and also the way 
serialization works. For example, in the previous posts I was trying to iterate 
on the _GenericApplicationPropertyOf... fields, and these are never really used,  
at least not in my case. The objects to use were the feature collection members:

citygml::CityModelType iCityModel ---> the root object
citygml::CityModelType::featureMember_sequence iSequence ---> its members
gml::FeaturePropertyType iFeatureProperty ---> one item

building::BuildingType iBuilding ---> an example of an object, in this case a 
building

Supposing the building has been created and personalised:

iFeatureProperty._Feature(iBuilding)
iSequence.push_back(iFeatureProperty);

Other objects can be added the same way as the building and at the end the 
sequence is assigned to the city model:

iCityModel.featureMember(iSequence);

Afterwards, the iteration and extraction of items and attributes is basically 
the reverse procedure.

Right now I'm having another issue. All the tags are generated the way they 
should be, except for one - the rather important <cityObjectMember>  tag. This 
is probably linked to the old substitution group story, since in cityGMLBase.xsd 
this item is defined like this:

<xs:element name="cityObjectMember" type="gml:FeaturePropertyType" 
substitutionGroup="gml:featureMember"/>

The cityObjectMember is actually the wrapper for each child of CityModel 
representing city objects (and not properties like appearance or other). Now, 
this differs from other items, for example the appearance item found at the same 
level in the hierarchy is like this:

<xs:complexType name="AppearancePropertyType">
   <xs:complexContent>
      <xs:extension base="gml:FeaturePropertyType">
         <xs:sequence minOccurs="0">
            <xs:element name="Appearance"  type="AppearanceType"/>
         </xs:sequence>
      </xs:extension>
   </xs:complexContent>
</xs:complexType>

When comparing these two in the generated .cxx files:

cityGMLBase.cxx:

  static const ::xsd::cxx::tree::element_factory_initializer< 0, char, 
::gml::FeaturePropertyType >
  _xsd_cityObjectMember_element_factory_init (
    "featureMember",
    "http://www.opengis.net/gml",
    "cityObjectMember",
    "http://www.opengis.net/citygml/1.0");

and appearance.cxx:

  static const ::xsd::cxx::tree::element_factory_initializer< 0, char,  
::citygml::appearance::AppearancePropertyType >
  _xsd_appearanceMember_element_factory_init (
    "featureMember",
    "http://www.opengis.net/gml",
    "appearanceMember",
    "http://www.opengis.net/appearance/1.0");

Considering iSequence to be the feature sequence of the city model, an 
<app:appearanceMember> tag with an <app:Appearance> child is generated well 
whenever I do:

appearance::AppearancePropertyType* iAppearanceProperty = new 
appearance::AppearancePropertyType();
appearance::AppearanceType* iAppearance = new appearance::AppearanceType();
[...appearance/texture  creation...]
iAppearanceProperty->Appearance(*iAppearance);
iSequence->push_back(*iAppearanceProperty);

However, when I try:

building::BuildingType* iBuilding = new building::BuildingType();
[...building creation...]
citygml::CityModelType::featureMember_type* iFeatureMember = new 
citygml::CityModelType::featureMember_type();
iFeatureMember->_Feature(*iBuilding);
iSequence->push_back(*iFeatureMember);

the result is a <gml:featureMember> tag. If I remove schema locations from the 
namespace map, the tag becomes something like:
>
with p2 being the unknown gml namespace, so it actually takes the namespace of 
the feature.

If I try:

citygml::CityModelType::featureMember_type* iFeatureMember = new 
citygml::CityModelType::featureMember_type();
//  this first line acts the same as and can be replaced by: 
FeaturePropertyType* iFeatureMember = new FeaturePropertyType();
citygml::CityModelType::featureMember_type::_Feature_type* iFeature = new 
citygml::CityModelType::featureMember_type::_Feature_type();
iFeatureMember->_Feature(*iFeature);
iSequence->push_back(*iFeatureMember);

upon creating this empty dummy object the tag remains <gml:featureMember>.

Please let me know if there is a way to obtain the right tag. Thank you.

Victor





________________________________
From: Boris Kolpackov <boris at codesynthesis.com>
To: Adrian Victor Manoliu <victor.manoliu at yahoo.com>
Cc: xsd-users at codesynthesis.com
Sent: Mon, February 28, 2011 3:48:35 PM
Subject: Re: [xsd-users] CityGML deserialization - CityModel generation

Hi Adrian,

Adrian Victor Manoliu <victor.manoliu at yahoo.com> writes:

> const std::string fName = "waldbruecke_v1.0.0.gml";
> std::auto_ptr<CityModelType> iCity(CityModel(fName, flags.dont_validate)); 
> 
> [...]
> 
> Now, once I have iCity, I simply want to iterate over its elements, that 
> is the Buildings, BuildingParts etc. by doing something like this (I have
> been doing this from the start):
> 
> CityModelType::_GenericApplicationPropertyOfCityModel_const_iterator ci;
> 
> for (ci  = iCity->_GenericApplicationPropertyOfCityModel().begin();
>      ci != iCity->_GenericApplicationPropertyOfCityModel().end();
>      ++ci)
> {
>     [...]
> }  
> 
> however in this case I  don't see how I could know what type to cast these 
> objects to

You need to study the GML/CityGML schemas to see which concrete elements
(and types) substitute which abstract elements.

Here is an example body of the above for-loop. Hopefully, it will get you
started:

for (ci  = iCity->_GenericApplicationPropertyOfCityModel().begin();
     ci != iCity->_GenericApplicationPropertyOfCityModel().end();
     ++ci)
{
  xml_schema::type& x (*ci);

  if (gml::FeaturePropertyType* cityObjectMember = 
        dynamic_cast<gml::FeaturePropertyType*> (&x))
  {
    gml::FeaturePropertyType::_Feature_const_iterator fi;

    for (fi = cityObjectMember->_Feature ().begin ();
         fi != cityObjectMember->_Feature ().end ();
         ++fi)
     {
      gml::AbstractFeatureType& f (*fi);

      if (citygml::building::BuildingType* b = 
        dynamic_cast<citygml::building::BuildingType*> (&f);
      {
        // We've got a building.
      }
      else if (...)
      {
        ...
      }
    }
  }
}

Boris


More information about the xsd-users mailing list