I have an XSD that I used with xsd.exe to generate an XML deserializer. However, at runtime, it does not deserialize the Bar or Timer definitions.
The relevant parts of the XSD are as follows:
<?xml version="1.0" encoding="utf-8"?>
<xs:schema targetNamespace="http://schemas.koboltentertainment.com"
elementFormDefault="qualified"
xmlns="http://schemas.koboltentertainment.com"
xmlns:mstns="http://schemas.koboltentertainment.com"
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<!-- Bar Definition -->
<xs:complexType name="Bar">
<xs:sequence>
<xs:element name="MaskAnim" type="Anim" />
</xs:sequence>
<xs:attribute name="name" type="xs:string" />
<xs:attribute name="anim" type="xs:positiveInteger" />
<xs:attribute name="recoverAnim" type="xs:positiveInteger" />
<xs:attribute name="min" type="xs:int" />
<xs:attribute name="max" type="xs:int" />
<xs:attribute name="valueBind" type="xs:string" />
<xs:attribute name="pos" type="vector" />
<xs:attribute name="layer" type="xs:byte" />
<xs:attribute name="width" type="xs:int" />
</xs:complexType>
<!-- CONTAINAZ -->
<xs:element name="Containers">
<xs:complexType>
<xs:sequence>
<xs:element ref="Container" minOccurs="1" maxOccurs="unbounded" />
</xs:sequence>
</xs:complexType>
</xs:element>
<!-- Container -->
<xs:element name="Container">
<xs:complexType>
<xs:sequence>
<xs:element name="Bar" type="Bar" minOccurs="1" maxOccurs="1" />
</xs:sequence>
<xs:attribute name="name" type="xs:string"/>
<xs:attribute name="id" type="xs:positiveInteger" />
<xs:attribute name="pos" type ="vector"/>
<xs:attribute name="layer" type="xs:byte" />
<xs:attribute name="anim" type="xs:positiveInteger" />
<xs:attribute name="alignment" type="alignment" />
</xs:complexType>
</xs:element>
The generated partial class looks as follows:
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(Namespace="http://schemas.koboltentertainment.com")]
public partial class Bar {
// data members, etc.
}
And lastly, the XML looks as follows:
<?xml version="1.0" encoding="UTF-8"?>
<UI xmlns="http://schemas.koboltentertainment.com">
<Info>
<Version>1.0.0.0</Version>
<LocalCoord>640,480</LocalCoord>
</Info>
<Files>
<Sprite>life.sff</Sprite>
<Anim>life.air</Anim>
</Files>
<!-- HUD implementation. All positions are relative to the top-left of the screen. -->
<HUD>
<Containers>
<!-- P1 LifeBar -->
<Container name="P1LifeBar" pos="6,69" layer="201" alignment="Left" anim="0" id="11">
<!-- Note here how we set the AnimSource element to self and the SFFSource to Player[0] (P1)'s SFF.
This means the animation should use P1's sprite data, but use our animation data. This is
similar to ChangeAnim2 in character code. -->
<Anim name="P1Portrait" pos="12,0" layer="199" anim="9000" id="12">
<!-- Valid Values for AnimSource and SFFSource: self, Player[x] -->
<AnimSource>self</AnimSource>
<SFFSource>Players[0]</SFFSource>
</Anim>
<!-- We set the bar min and max according to P1's constants. We bind it to P1's Life property. -->
<Bar min="0" max="Players[0].Constants.Data.Life" valueBind="Players[0].Life" pos="6,69" layer="200"
width="263" anim="1" recoverAnim="2" id="13">
<Mask anim="10"/>
</Bar>
<!-- Here we have our first Text. It binds to P1's Name.-->
<Text font="Aqua Grotesque" pos="24,56" valueBind="Players[0].Name" alignment="Left"/>
</Container>
<!-- P2 LifeBar -->
<Container name="P2LifeBar" pos="6,69" layer="201" alignment="Right" anim="3" id="14">
<Anim name="P2Portrait" pos="614,0" layer="199" anim="9001" id="15">
<AnimSource>self</AnimSource>
<SFFSource>Players[1]</SFFSource>
</Anim>
<Bar min="0" max="Players[1].Constants.Data.Life" valueBind="Players[1].Life" pos="6,69" layer="200"
width="263" anim="4" recoverAnim="5" id="16">
<Mask anim="10"/>
</Bar>
<Text font="Aqua Grotesque" pos="400,56" valueBind="Players[0].Name" alignment="Right"/>
</Container>
</Containers>
<!-- Timer. It's like Text with additional timer options, such as whether or not it is affected by Turbo. -->
<Timer font="timer.xnb" pos="312,32" turboTime="false" valueBind="RoundTime">
<!-- These are the times that are valid for this timer. These will be selectable from Options menu. -->
<ValidTimes>
<TimeOption>0</TimeOption>
<TimeOption>30</TimeOption>
<TimeOption>60</TimeOption>
<TimeOption>90</TimeOption>
</ValidTimes>
<TicksPerCount>60</TicksPerCount>
</Timer>
</HUD>
</UI>
Containers, Container, and most of what they contain are deserialized properly, but Bar is not. It always returns null at runtime. Why is it not deserializing?
I'm in no way familiar with xsd. However, when something doesn't deserialize its usually because the data is invalid.
In this case I'm guessing its because Bar.min
and Bar.max
are defined as int
s, and "Players[1].Constants.Data.Life"
doesn't look anything like an int.