I'm currently working on a CityGML (de)serializer - I need C# classes for certain corresponding objects - and I'm having some trouble with the root class I need for the System.Xml.Serialization.XmlSerializer instance. I don't know how familiar everyone here is with CityGML, but here's a description of the situation. I've also described how I created my classes, if you wish to skip this you can start reading from the //* mark:
CityGML is composed of several .xsd files, each being a module describing a certain type of elements (appearance.xsd, transports.xsd, building.xsd, vegetation.xsd etc.), also having a root file, CityGML.xsd. As you might expect, each of the modules requires elements from this root file. Then there's also the fact that CityGML actually inherits a lot from GML, so imports from GML .xsd files are also necessary.
So far, in terms of C# class generation, I've tried two approaches, both using the classic xsd.exe: - the creation of a single .cs file which will include all the CityGML classes I need - a single command line:
xsd gml/feature.xsd gml/xlinks.xsd gml/geometryBasic2d.xsd gml/geometryComplexes.xsd gml/geometryPrimitives.xsd gml/smil20.xsd
gml/smil20-language.xsd citygml/xAL.xsd citygml/appearance.xsd citygml/building.xsd citygml/cityFurniture.xsd citygml/cityObjectGroup.xsd
citygml/generics.xsd citygml/landUse.xsd citygml/relief.xsd citygml/texturedSurface.xsd citygml/transportation.xsd citygml/vegetation.xsd
citygml/waterBody.xsd citygml/CityGML.xsd citygml/cityGMLBase.xsd /classes /fields /namespace:CityGML
- the creation of a .cs file for each of the CityGML modules - one command line for each module:
xsd citygml/xAL.xsd /classes /namespace:xAL /o:out
xsd gml/feature.xsd citygml/xAL.xsd gml/geometryAggregates.xsd gml/xlinks.xsd
citygml/cityGMLBase.xsd /classes /namespace:CityGMLBase /o:out
xsd gml/feature.xsd citygml/cityGMLBase.xsd citygml/xAL.xsd gml/geometryAggregates.xsd
gml/xlinks.xsd citygml/appearance.xsd /classes /namespace:CityGMLAppearance /o:out
xsd gml/feature.xsd citygml/cityGMLBase.xsd citygml/xAL.xsd gml/geometryAggregates.xsd gml/xlinks.xsd citygml/building.xsd /classes /namespace:CityGMLBuilding /o:out
xsd gml/feature.xsd citygml/cityGMLBase.xsd citygml/xAL.xsd gml/geometryAggregates.xsd gml/xlinks.xsd citygml/cityFurniture.xsd /classes /namespace:CityGMLCityFurniture /o:out
xsd citygml/cityGMLBase.xsd gml/feature.xsd gml/xlinks.xsd citygml/xAL.xsd gml/geometryAggregates.xsd citygml/cityObjectGroup.xsd /classes /namespace:CityGMLCityObjectGroup /o:out
xsd gml/feature.xsd citygml/cityGMLBase.xsd citygml/xAL.xsd gml/geometryAggregates.xsd gml/xlinks.xsd citygml/generics.xsd /classes /namespace:CityGMLGenerics /o:out
xsd gml/feature.xsd citygml/cityGMLBase.xsd citygml/xAL.xsd gml/geometryAggregates.xsd gml/xlinks.xsd citygml/landUse.xsd /classes /namespace:CityGMLLandUse /o:out
xsd citygml/cityGMLBase.xsd citygml/xAL.xsd gml/xlinks.xsd citygml/cityFurniture.xsd gml/coverage.xsd citygml/relief.xsd /classes /namespace:CityGMLRelief /o:out
xsd gml/feature.xsd citygml/cityGMLBase.xsd citygml/xAL.xsd gml/geometryAggregates.xsd gml/xlinks.xsd citygml/texturedSurface.xsd /classes /namespace:CityGMLTexturedSurface /o:out
xsd gml/feature.xsd citygml/cityGMLBase.xsd citygml/xAL.xsd gml/geometryComplexes.xsd gml/xlinks.xsd citygml/transportation.xsd /classes /namespace:CityGMLTransportation /o:out
xsd gml/feature.xsd citygml/cityGMLBase.xsd citygml/xAL.xsd gml/geometryAggregates.xsd
gml/xlinks.xsd citygml/vegetation.xsd /classes /namespace:CityGMLVegetation /o:out
xsd gml/feature.xsd citygml/cityGMLBase.xsd citygml/xAL.xsd gml/geometryAggregates.xsd gml/xlinks.xsd citygml/waterBody.xsd /classes /namespace:CityGMLWaterBody /o:out
For each of the commands, the last .xsd is the desired module, while the others are necessary imports.
Unfortunately, though xsd.exe deals with imports from other .xsd files and it creates classes of the required file as well as from the imported files, it does this quite "directly", stacking all of these classes in one .cs file. Apparently there's no way to separate the desired classes from the imported classes in different .cs files. Consequently, my first question would be ARE THERE ANY (DE)SERIALIZATION TOOLS, SIMILAR TO XSD.EXE, WHICH DEAL WITH IMPORTED .XSD FILES AND CREATE A CERTAIN .CS FILE HIERARCHY ? This would avoid repetition of, for example, the classes of feature.xsd in all of the above module .cs files.
//*
Moving on, the issue which actually causes me trouble is related to the XmlSerializer instance, which cannot be created because the base CityGML object type, CityModelType, which is also the root class in the entire hierarchy, is not entirely valid:
System.Xml.Serialization.XmlSerializer x = new System.Xml.Serialization.XmlSerializer(typeof(CityModelType));
This assignment first yielded an error concerning the use of XmlTextAttribute to define a string[], which rendered the "reflection" of CityModelType impossible. I replaced XmlTextAttribute with XmlAttributeAttribute and the current messages, whose origin I haven't been able to trace, are these (yes, I am working in French):
System.InvalidOperationException: Impossible de générer une classe temporaire (result=1).
error CS0030: Impossible de convertir le type 'CityGML.LineStringSegmentType[]' en 'CityGML.LineStringSegmentType'
error CS0030: Impossible de convertir le type 'CityGML.LineStringSegmentType[]' en 'CityGML.LineStringSegmentType'
error CS0030: Impossible de convertir le type 'CityGML.LineStringSegmentType[]' en 'CityGML.LineStringSegmentType'
error CS0029: Impossible de convertir implicitement le type 'CityGML.LineStringSegmentType' en 'CityGML.LineStringSegmentType[]'
error CS0029: Impossible de convertir implicitement le type 'CityGML.LineStringSegmentType' en 'CityGML.LineStringSegmentType[]'
error CS0029: Impossible de convertir implicitement le type 'CityGML.LineStringSegmentType' en 'CityGML.LineStringSegmentType[]'
First of all, the only occurences of LineStringSegmentType are related to curves, which I am not using in my .gml file. They are defined like this:
public partial class LineStringSegmentType : AbstractCurveSegmentType {
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute("coordinates", typeof(CoordinatesType))]
[System.Xml.Serialization.XmlElementAttribute("pointProperty", typeof(PointPropertyType))]
[System.Xml.Serialization.XmlElementAttribute("pointRep", typeof(PointPropertyType))]
[System.Xml.Serialization.XmlElementAttribute("pos", typeof(DirectPositionType))]
[System.Xml.Serialization.XmlElementAttribute("posList", typeof(DirectPositionListType))]
[System.Xml.Serialization.XmlChoiceIdentifierAttribute("ItemsElementName")]
public object[] Items;
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute("ItemsElementName")]
[System.Xml.Serialization.XmlIgnoreAttribute()]
public ItemsChoiceType2[] ItemsElementName;
/// <remarks/>
[System.Xml.Serialization.XmlAttributeAttribute()]
public CurveInterpolationType interpolation;
/// <remarks/>
[System.Xml.Serialization.XmlIgnoreAttribute()]
public bool interpolationSpecified;
public LineStringSegmentType() {
this.interpolation = CurveInterpolationType.linear;
}
}
...and they are used here:
public partial class TinType : TriangulatedSurfaceType {
/// <remarks/>
[System.Xml.Serialization.XmlArrayItemAttribute("LineStringSegment", typeof(LineStringSegmentType), IsNullable=false)]
public LineStringSegmentType[][] stopLines;
/// <remarks/>
[System.Xml.Serialization.XmlArrayItemAttribute("LineStringSegment", typeof(LineStringSegmentType), IsNullable=false)]
public LineStringSegmentType[][] breakLines;
/// <remarks/>
public LengthType maxLength;
/// <remarks/>
public TinTypeControlPoint controlPoint;
}
...coming from this gml:geometryPrimitives.xsd fragment:
<complexType name="TinType">
[...]
<complexContent>
<extension base="gml:TriangulatedSurfaceType">
<sequence>
<element name="stopLines" type="gml:LineStringSegmentArrayPropertyType" minOccurs="0" maxOccurs="unbounded">
[...]
</element>
<element name="breakLines" type="gml:LineStringSegmentArrayPropertyType" minOccurs="0" maxOccurs="unbounded">
[...]
</element>
<element name="maxLength" type="gml:LengthType">
[...]
</element>
<element name="controlPoint">
[...]
<complexType>
<choice>
<element ref="gml:posList"/>
<group ref="gml:geometricPositionGroup" minOccurs="3" maxOccurs="unbounded"/>
</choice>
</complexType>
</element>
</sequence>
</extension>
</complexContent>
</complexType>
<complexType name="LineStringSegmentArrayPropertyType">
<sequence>
<element ref="gml:LineStringSegment" minOccurs="0" maxOccurs="unbounded"/>
</sequence>
</complexType>
I don't see where the problem is, and this is quite strange. Hope to hear from you soon. Thanks.
Cheers, Victor
"ARE THERE ANY (DE)SERIALIZATION TOOLS, SIMILAR TO XSD.EXE, WHICH DEAL WITH IMPORTED .XSD FILES AND CREATE A CERTAIN .CS FILE HIERARCHY ?"
Yes indeed, I use Xsd2Code, which was a god send after I had similar problems iwht xsd.exe