XML deserialization notes
by John Quigley · in Torque X 3D · 11/07/2006 (10:26 am) · 5 replies
We really need an xml schema and some better documentation for the deserializer. Here is the start of an writeup I was doing on the deserializer, which I didn't include in the beta because it is really incomplete. But for the curious, here it is:
Deserialization overview:
Deserialization works by unpacking a single top level object that represents the XML,
usually "LevelData". This top level object should contain appropriate fields and properties
to store the entire structure of the xml document.
Fields and properties of the object are deserialized. For each child element in the XML, the
element name is checked to see if there is a field/property of the same name in the object. If so,
the value in the XML is placed into the field/property. If not, the element is ignored.
Only the public fields, and properties with both set and get accessors, are deserialized.
You can deserialize into non-public fields and properties by specifing
[TorqueXmlDeserializeInclude] on the attribute. You can specify that an otherwise accessible
property be ignored by adding [XmlIgnore]. You can remap element names (so that the property name
can differ from the Xml) by using [XmlElement(ElementName="X")]. This capability is used in the
T2DCollisionComponent, to deserialize the collision images into a special property.
If the type of a field/property is a list, the deserializer recurses on the child elements to
build the contents of that list. See builtin list types for information about what the available
list types are.
The top level object, and top level members of lists, must have type mappings so that the
deserializer knows what kind of instance to create for them. There are certain "default"
type mappings for built in object; for instance, using an element named DefaultEffect will
get mapped into the DefaultEffect class in the engine. These default mappings are defined in
LevelData. A game can also get the type map object from LevelData and add its own types prior
to deserialization.
If default type mapping is available, a "type" attribute must be specified, or the element will
be ignored. The type should be the fully qualified namespace of the target type, e.g.
type="GarageGames.Torque.Engine.Materials.DXEffects.DefaultEffect". This type attribute also
takes precidence over the default type mapping so can be used to override it.
Fields and properties of an object do not need type mappings, because they are part of
an object whose type is known, thus their types are known.
Objects and Object types
NameRef (nameRef="x") attribute
Valid in fields or properties, but only if field type is reference, interface, or abstract
(i.e no value types).
Valid in aggregate elements.
Not valid in List elements. (may change this)
ObjTypeRef (objTypeRef="x") attribute
Valid in fields or properties of type TorqueObjectType.
Valid in aggregate elements (will assign them to the named instance of TorqueObjectType)
Not valid in List elements. (may change this)
Builtin List Types (no attribute to specify a list, only builtins supported):
Anything that implements IList, generic or specialized.
Any array
TorqueComponentContainer
Builtin "In Place" types (attribute inPlace="true"):
TorqueComponentContainer (may remove this and make it be specified from XML)
LevelData's Object,Materials,and SceneData lists
Builtin Aggregate types (no attribute):
TorqueObjectType
Acceptable List content elements:
Reference and Value types appropriate for the list
Primitives
Acceptable Aggregate content elements:
Namerefs
ObjTypeRefs
Reference and Value types appropriate for the aggregation
Deserialization overview:
Deserialization works by unpacking a single top level object that represents the XML,
usually "LevelData". This top level object should contain appropriate fields and properties
to store the entire structure of the xml document.
Fields and properties of the object are deserialized. For each child element in the XML, the
element name is checked to see if there is a field/property of the same name in the object. If so,
the value in the XML is placed into the field/property. If not, the element is ignored.
Only the public fields, and properties with both set and get accessors, are deserialized.
You can deserialize into non-public fields and properties by specifing
[TorqueXmlDeserializeInclude] on the attribute. You can specify that an otherwise accessible
property be ignored by adding [XmlIgnore]. You can remap element names (so that the property name
can differ from the Xml) by using [XmlElement(ElementName="X")]. This capability is used in the
T2DCollisionComponent, to deserialize the collision images into a special property.
If the type of a field/property is a list, the deserializer recurses on the child elements to
build the contents of that list. See builtin list types for information about what the available
list types are.
The top level object, and top level members of lists, must have type mappings so that the
deserializer knows what kind of instance to create for them. There are certain "default"
type mappings for built in object; for instance, using an element named DefaultEffect will
get mapped into the DefaultEffect class in the engine. These default mappings are defined in
LevelData. A game can also get the type map object from LevelData and add its own types prior
to deserialization.
If default type mapping is available, a "type" attribute must be specified, or the element will
be ignored. The type should be the fully qualified namespace of the target type, e.g.
type="GarageGames.Torque.Engine.Materials.DXEffects.DefaultEffect". This type attribute also
takes precidence over the default type mapping so can be used to override it.
Fields and properties of an object do not need type mappings, because they are part of
an object whose type is known, thus their types are known.
Objects and Object types
NameRef (nameRef="x") attribute
Valid in fields or properties, but only if field type is reference, interface, or abstract
(i.e no value types).
Valid in aggregate elements.
Not valid in List elements. (may change this)
ObjTypeRef (objTypeRef="x") attribute
Valid in fields or properties of type TorqueObjectType.
Valid in aggregate elements (will assign them to the named instance of TorqueObjectType)
Not valid in List elements. (may change this)
Builtin List Types (no attribute to specify a list, only builtins supported):
Anything that implements IList, generic or specialized.
Any array
TorqueComponentContainer
Builtin "In Place" types (attribute inPlace="true"):
TorqueComponentContainer (may remove this and make it be specified from XML)
LevelData's Object,Materials,and SceneData lists
Builtin Aggregate types (no attribute):
TorqueObjectType
Acceptable List content elements:
Reference and Value types appropriate for the list
Primitives
Acceptable Aggregate content elements:
Namerefs
ObjTypeRefs
Reference and Value types appropriate for the aggregation
About the author
#2
@Jonathon: Using VS 2005, I generated a schema from the XML. Then, it's easy to use microsoft's XML Notepad or other XML tool to modify or generate a new XML file that uses the same schema. However, this method only generates a schema as good as the file it's being generated from. Because the schema can change somewhat based upon the .NET class properties and the classes that you can create, I don't think a 'complete' schema could be generated for anything but the classes directly in the framework, so it wouldn't support all of the user defined classes.
Example custom Schema portion for TankBuster:
I can also send you the schema I generated if you don't have VS 2005.
11/08/2006 (11:38 pm)
@John: Thanks for the post John. It would also increase clarity if you were to provide a small simple XML file that contained all of the elements you mentioned, along with snippets from the file next to each item you you are discussing.@Jonathon: Using VS 2005, I generated a schema from the XML. Then, it's easy to use microsoft's XML Notepad or other XML tool to modify or generate a new XML file that uses the same schema. However, this method only generates a schema as good as the file it's being generated from. Because the schema can change somewhat based upon the .NET class properties and the classes that you can create, I don't think a 'complete' schema could be generated for anything but the classes directly in the framework, so it wouldn't support all of the user defined classes.
Example custom Schema portion for TankBuster:
I can also send you the schema I generated if you don't have VS 2005.
#3
Thanks for the heads up though =).
11/09/2006 (6:05 am)
@Tim - I do in fact have vs.net 2005, so too had generated the schema from the xml included. As you've pointed out, this wouldn't include anything that isn't currently in the xml, which is why I wanted GG to generate a complete schema for our use. I also generated a schema from the actual txscene file as well since it is in fact XML.Thanks for the heads up though =).
#4
11/09/2006 (8:42 am)
Can i get a quick tutorial to this XML Scheme stuff? A simple link would work but i have never used them and while i bet they are simple a quick walk through of how they work, what i plug them into ect... would make me feel less lost.
Torque 3D Owner Jonathon Stevens