从 XSD 创建的 类 的反序列化不包含所有数据

Deserialization to classes created from XSD does not contain all data

我想将包含运动数据的 TCX 文件反序列化到我的 local/temporary 对象中。我使用了 XSD schema describing 这样的格式,并使用 xsd2code 创建了 类。

之后,我能够将 XML 反序列化为正确的对象,并且反序列化器没有抛出任何异常。但是当我开始扩展组件的行为时,我注意到有些字段不是正确的全字段。

问题是关于读取标签曲目。子结构中的反序列化 Lap 正确显示所有数据,但 Tracks 编号显示为 0。

有什么方法可以触发解串器来正确解释它吗?我错过了一些属性吗?为什么没有异常也读不准

我知道,很难解释并将所有需要的 类 放入评论中 - 所以我分享我的 current status here 并写下:GetUnifiedData_WhenTrackPointsAreGivenInTcx_UnifiedTrackPointShouldRetreiveIt() 没有通过并且显示我的问题。

<Activities>
 <Activity Sport="Running">
  <Id>2015-01-25T12:14:34Z</Id>
  <Lap StartTime="2015-01-25T12:14:34Z">
    <TotalTimeSeconds>507.0989990</TotalTimeSeconds>
    <DistanceMeters>1000.0000000</DistanceMeters>
    <MaximumSpeed>2.5790000</MaximumSpeed>
    <Calories>95</Calories>
    <AverageHeartRateBpm xsi:type="HeartRateInBeatsPerMinute_t">
      <Value>155</Value>
    </AverageHeartRateBpm>
    <MaximumHeartRateBpm xsi:type="HeartRateInBeatsPerMinute_t">
      <Value>173</Value>
    </MaximumHeartRateBpm>
    <Intensity>Resting</Intensity>
    <TriggerMethod>Distance</TriggerMethod>
    <Track>
      <Trackpoint>
        <Time>2015-01-25T12:14:34Z</Time>
        <Position>
          <LatitudeDegrees>50.8918607</LatitudeDegrees>
          <LongitudeDegrees>16.7403161</LongitudeDegrees>
        </Position>
        <AltitudeMeters>233.1999969</AltitudeMeters>
        <DistanceMeters>0.0000000</DistanceMeters>
        <HeartRateBpm xsi:type="HeartRateInBeatsPerMinute_t">
          <Value>88</Value>
        </HeartRateBpm>
        <Extensions>
          <TPX xmlns="http://www.garmin.com/xmlschemas/ActivityExtension/v2" CadenceSensor="Footpod">
            <Speed>0.0000000</Speed>
          </TPX>
        </Extensions>
      </Trackpoint>
    </Track>
    <Track>
    </Track>
    <Extensions>
      <FatCalories xmlns="http://www.garmin.com/xmlschemas/FatCalories/v1">
        <Value>0</Value>
      </FatCalories>
      <LX xmlns="http://www.garmin.com/xmlschemas/ActivityExtension/v2">
        <AvgSpeed>1.9720000</AvgSpeed>
      </LX>
    </Extensions>
  </Lap>
</Activity>
</Activities>

问题是你的数据模型不对。在下面的摘录中,您将在 Lap 元素下方看到两个 Track 元素:

<?xml version="1.0" encoding="utf-16" standalone="no"?>
<TrainingCenterDatabase xmlns="http://www.garmin.com/xmlschemas/TrainingCenterDatabase/v2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.garmin.com/xmlschemas/ActivityExtension/v2 http://www.garmin.com/xmlschemas/ActivityExtensionv2.xsd http://www.garmin.com/xmlschemas/FatCalories/v1 http://www.garmin.com/xmlschemas/fatcalorieextensionv1.xsd http://www.garmin.com/xmlschemas/TrainingCenterDatabase/v2 http://www.garmin.com/xmlschemas/TrainingCenterDatabasev2.xsd">
  <Activities>
    <Activity Sport="Running">
      <Id>2015-01-25T12:14:34Z</Id>
      <Lap StartTime="2015-01-25T12:14:34Z">
        <Track>
          <Trackpoint>
            <Time>2015-01-25T12:14:34Z</Time>
            ... etc etc
          </Trackpoint>
          <Trackpoint>
            ... etc etc
          </Trackpoint>
        </Track>
        <Track>
          <Trackpoint>
            ... etc etc
          <Trackpoint>
        </Track>

但是,在您的数据模型中,TrackLap 的单例 属性,包含 TrackPoint_t 个条目的数组。当 XmlSerializer 遇到多个 Track 元素时,它无法反序列化它们。

因此您的数据模型需要如下所示。介绍一个中间人 class Track_t:

[System.Xml.Serialization.XmlTypeAttribute(Namespace = "http://www.garmin.com/xmlschemas/TrainingCenterDatabase/v2")]
public class Track_t
{
    public Track_t()
    {
        this.Track = new List<Trackpoint_t>();
    }

    [System.Xml.Serialization.XmlElement("TrackPoint", typeof(Trackpoint_t), IsNullable = false)]
    public List<Trackpoint_t> Track { get; set; }
}

并修改ActivityLap_t如下:

[System.CodeDom.Compiler.GeneratedCodeAttribute("System.Xml", "4.0.30319.34234")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(Namespace = "http://www.garmin.com/xmlschemas/TrainingCenterDatabase/v2")
]
public partial class ActivityLap_t
{
    private List<Track_t> _track;  // Change type to `Track_t`

    public ActivityLap_t()
    {
        this._extensions = new Extensions_t();
        this._track = new List<Track_t>(); // Change type to `Track_t`
        this._maximumHeartRateBpm = new HeartRateInBeatsPerMinute_t();
        this._averageHeartRateBpm = new HeartRateInBeatsPerMinute_t();
    }

    // Change type to `Track_t` and change attribute to `XmlElement`
    [System.Xml.Serialization.XmlElement("Track", typeof(Track_t), IsNullable = false)]
    public List<Track_t> Track
    {
        get { return this._track; }
        set { this._track = value; }
    }

    // Remainder unchanged.
}

您还需要以同样的方式修改Course_t

xsd 确实指定了类型 Track_t 的存在,并且 ActivityLap_t 可以包含无限数量的 Track 这种类型的元素,所以不知何故 XSD 被错误地转换为 classes:

  <xsd:complexType name="ActivityLap_t">
    <xsd:sequence>
      <xsd:element name="TotalTimeSeconds" type="xsd:double" />
      <xsd:element name="DistanceMeters" type="xsd:double" />
      <xsd:element name="MaximumSpeed" type="xsd:double" minOccurs="0" />
      <xsd:element name="Calories" type="xsd:unsignedShort" />
      <xsd:element name="AverageHeartRateBpm" type="HeartRateInBeatsPerMinute_t" minOccurs="0" />
      <xsd:element name="MaximumHeartRateBpm" type="HeartRateInBeatsPerMinute_t" minOccurs="0" />
      <xsd:element name="Intensity" type="Intensity_t" />
      <xsd:element name="Cadence" type="CadenceValue_t" minOccurs="0" />
      <xsd:element name="TriggerMethod" type="TriggerMethod_t" />
      <xsd:element name="Track" type="Track_t" minOccurs="0" maxOccurs="unbounded" />  <!-- Notice that maxOccurs is unbounded so "Track" needs to be a list  -->
      <xsd:element name="Notes" type="xsd:string" minOccurs="0" />
      <xsd:element name="Extensions" type="Extensions_t" minOccurs="0">
        <xsd:annotation>
          <xsd:documentation>
            You can extend Training Center by adding your own elements from another schema here.
          </xsd:documentation>
        </xsd:annotation>
      </xsd:element>
    </xsd:sequence>
    <xsd:attribute name="StartTime" type="xsd:dateTime" use="required" />
  </xsd:complexType>

  <xsd:complexType name="Track_t">
    <xsd:sequence>
      <xsd:element name="TrackPoint" type="TrackPoint_t" maxOccurs="unbounded" />
    </xsd:sequence>
  </xsd:complexType>