C#与IXmlSerializable的

问题描述:

反序列化我有这样的XML:C#与IXmlSerializable的

<data>  
    <audit_values> 
    <audit_value> 
     <channel>2</channel> 
     <week> 
     <mo_th>6,501698000000</mo_th> 
     <fr>8,414278000000</fr> 
     <sa>9,292674000000</sa> 
     <sun>8,551982000000</sun> 
     <holid>7,164605000000</holid> 
     </week> 
    </audit_value> 
    <audit_value> 
     <channel>1</channel> 
     <week> 
     <mo_th>6,501698000000</mo_th> 
     <fr>8,414278000000</fr> 
     <sa>9,292674000000</sa> 
     <sun>8,551982000000</sun> 
     <holid>7,164605000000</holid> 
     </week> 
    </audit_value> 
    </audit_values> 
</data> 

,我需要它反序列化类。 但问题是,这周将在未来的变化(这将是包含更多的元素,并把它们的名字我不知道)

数据:

[XmlRoot("data")] 
public class Data 
{ 
    [XmlArray("audit_values")] 
    [XmlArrayItem("audit_value", IsNullable = true)] 
    public AuditValue[] AuditValues { get; set; } 
} 

AuditValue:

[XmlRoot("audit_value")] 
public class AuditValue 
{ 
    [XmlElement("week", typeof(TVR))] 
    public Week Week; 
} 

周:

[XmlRoot("week")] 
public class Week : IXmlSerializable 
{ 
    public Dictionary<string, double> Values = new Dictionary<string, double>(); 

    public XmlSchema GetSchema() 
    { 
     return null; 
    } 

    public void ReadXml(XmlReader reader) 
    { 
     reader.Read(); 
     var sub = reader.ReadSubtree(); 
     do 
     { 
      if (sub.NodeType == XmlNodeType.Element) 
      { 
       string name = sub.Name; 
       string val = sub.ReadElementContentAsString(); 
       Values.Add(name, Convert.ToDouble(val)); 
      } 
     } while (sub.Read()); 
    } 

    public void WriteXml(XmlWriter writer) 
    { 

    } 
} 

但deserializat后离子我只有一个元素,只有一个字典值中记录。我做错了什么?

GitHub上: https://github.com/olegletynain/XmlTest/tree/master/XmlTestRead

+0

[使用XmlSerializer反序列化随机/未知类型](http:// stackoverflow。com/questions/8210386/deserialize-random-unknown-types-with-xmlserializer) – GSerg

+0

对不起,但我在实现IXmlSerializable时遇到了问题,并且没有未知类型。它不是重复的 –

+0

您是否尝试添加断点并调试代码? –

我调整基于@Matthew粉饰在评论部分知道你的ReadXml方法和下面的方法做工作:

public void ReadXml(XmlReader reader) 
{ 
    Values = XElement.Parse(reader.ReadOuterXml()) 
     .Elements() 
     .ToDictionary(k => k.Name.ToString(), v => double.Parse(v.Value)); 
} 

作为一个侧面说明,你只需要XmlRoot实际的根元素不是每个所以我将它从AuditValue和Week中删除。我也不知道TVR是什么。它没有用“typeof(TVR)”编译,所以我也删除了它。

为了完整起见,这里是我的版本的类:

[XmlRoot("data")] 
public class Data 
{ 
    [XmlArray("audit_values")] 
    [XmlArrayItem("audit_value", IsNullable = true)] 
    public AuditValue[] AuditValues { get; set; } 
} 

public class AuditValue 
{ 
    [XmlElement("week")] 
    public Week Week; 
} 

public class Week : IXmlSerializable 
{ 
    public Dictionary<string, double> Values = new Dictionary<string, double>(); 

    public XmlSchema GetSchema() 
    { 
     return null; 
    } 

    public void ReadXml(XmlReader reader) 
    { 
     Values = XElement.Parse(reader.ReadOuterXml()) 
      .Elements() 
      .ToDictionary(k => k.Name.ToString(), v => double.Parse(v.Value)); 
    } 

    public void WriteXml(XmlWriter writer) 
    { 

    } 
} 
+0

谢谢,今晚我自己制作了一个方法,不使用XElement和Linq –

试试这个。 XmlElement消除了你没有的标签。值的末尾有一个额外的's'。

From 
    [XmlArray("audit_values")] 
    [XmlArrayItem("audit_value", IsNullable = true)] 
    public AuditValue[] AuditValues { get; set; } 
​To 
    [XmlElement("audit_value")] 
    public AuditValue[] AuditValues { get; set; } 
+0

噢,对不起,第一次它是xml中的一个错误。 –

+0

您不需要两级标签只需。使用XlEement而不是XmlArray可以去掉不必要的标签。 – jdweng

+0

对不起,但你错了 –

你应该考虑使用DataContractSerializer的,而不是XmlSerializer的和执行上的DataContract类IExtensibleDataObject接口。

实现IExtensibleDataObject允许DataContract类在ExtensionData字段中保留未知信息,这样可以防止在被反序列化的XML包含未知元素后丢失,然后重新序列化并保存。

你审计类将是这个样子:

[DataContract(Name = "audit_value", Namespace = "")] 
public class AuditValue : IExtensibleDataObject 
{ 
    [DataMember(Name = "channel")] 
    public int Channel { get; set; } 

    [DataMember(Name = "week")] 
    public Week Week { get; set; } 

    public ExtensionDataObject ExtensionData { get; set; } 
} 

[DataContract(Name = "week", Namespace = "")] 
public class Week : IExtensibleDataObject 
{ 
    [DataMember(Name = "mo_th")] 
    public Decimal MondayThroughThursday { get; set; } 

    public ExtensionDataObject ExtensionData { get; set; } 
} 

你仍然需要更新您的代码以反序列化的附加元素波苏斯,但至少底层数据将一直持续到你身边到它。

错误是在ReadXml方法,现在我把它改成这样:

​​

我工作正常。此解决方案不使用XElement和Linq,@Volkan Paksoy提供了易于理解的XElement方法