XML 反序列化未将值加载到 class
XML deserialization not loading values into class
我有以下 XML,我为其自动生成了一个 class。
生成 class 后,我必须进行一些调整才能获得 PayrollEmployeePayrollDate
和 PayrollEmployeePayrollCategoryWorkCode
classes。由于我进行了调整,两个 classes 都已加载,但所有值均为空。除非在反序列化过程中使用它们,否则我不会收到任何错误。为什么我的值没有加载到 class?
<Payroll>
<StartDate>2015-02-22</StartDate>
<EndDate>2015-02-28</EndDate>
<PostedDate>2015-02-28</PostedDate>
<Employee EmployeeId="123456">
<EmployeePayStatus></EmployeePayStatus>
<PayrollStoreNumber>1111</PayrollStoreNumber>
<ReviewedDate></ReviewedDate>
<PayrollCategory Category="OT">
</PayrollCategory>
<PayrollCategory Category="DT">
</PayrollCategory>
<PayrollCategory Category="REGULAR">
<PayrollDate>2015-02-23</PayrollDate>
<Hours>5.97</Hours>
<WorkCode code="888">
<TotalHours>5.97</TotalHours>
</WorkCode>
<PayrollDate>2015-02-24</PayrollDate>
<Hours>6.07</Hours>
<WorkCode code="888">
<TotalHours>6.07</TotalHours>
</WorkCode>
<PayrollDate>2015-02-25</PayrollDate>
<Hours>6.00</Hours>
<WorkCode code="888">
<TotalHours>6.00</TotalHours>
</WorkCode>
<PayrollDate>2015-02-26</PayrollDate>
<Hours>8.44</Hours>
<WorkCode code="888">
<TotalHours>8.44</TotalHours>
</WorkCode>
<PayrollDate>2015-02-27</PayrollDate>
<Hours>7.90</Hours>
<WorkCode code="888">
<TotalHours>7.90</TotalHours>
</WorkCode>
</PayrollCategory>
<PayrollCategory Category="SICK">
</PayrollCategory>
<PayrollCategory Category="VACATION">
</PayrollCategory>
<PayrollCategory Category="HOLIDAY">
</PayrollCategory>
<PayrollCategory Category="RT">
</PayrollCategory>
<PayrollCategory Category="EO">
</PayrollCategory>
<PayrollCategory Category="RSA">
</PayrollCategory>
</Employee>
<Employee EmployeeId="987654">
<EmployeePayStatus></EmployeePayStatus>
<PayrollStoreNumber>1111</PayrollStoreNumber>
<ReviewedDate></ReviewedDate>
<PayrollCategory Category="OT">
</PayrollCategory>
<PayrollCategory Category="DT">
</PayrollCategory>
<PayrollCategory Category="REGULAR">
<PayrollDate>2015-02-23</PayrollDate>
<Hours>6.38</Hours>
<WorkCode code="888">
<TotalHours>6.38</TotalHours>
</WorkCode>
<PayrollDate>2015-02-24</PayrollDate>
<Hours>6.82</Hours>
<WorkCode code="888">
<TotalHours>6.82</TotalHours>
</WorkCode>
<PayrollDate>2015-02-25</PayrollDate>
<Hours>6.83</Hours>
<WorkCode code="888">
<TotalHours>6.83</TotalHours>
</WorkCode>
<PayrollDate>2015-02-26</PayrollDate>
<Hours>7.32</Hours>
<WorkCode code="888">
<TotalHours>7.32</TotalHours>
</WorkCode>
<PayrollDate>2015-02-27</PayrollDate>
<Hours>7.40</Hours>
<WorkCode code="888">
<TotalHours>7.40</TotalHours>
</WorkCode>
<PayrollDate>2015-02-28</PayrollDate>
<Hours>4.17</Hours>
<WorkCode code="888">
<TotalHours>4.17</TotalHours>
</WorkCode>
</PayrollCategory>
<PayrollCategory Category="SICK">
</PayrollCategory>
<PayrollCategory Category="VACATION">
</PayrollCategory>
<PayrollCategory Category="HOLIDAY">
</PayrollCategory>
<PayrollCategory Category="RT">
</PayrollCategory>
<PayrollCategory Category="EO">
</PayrollCategory>
<PayrollCategory Category="RSA">
</PayrollCategory>
</Employee>
</Payroll>
这是我正在使用的 class。
namespace PayrollProcessor.BL
{
/// <remarks/>
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
[System.Xml.Serialization.XmlRootAttribute(Namespace = "", IsNullable = false)]
public class Payroll
{
private System.DateTime startDateField;
private System.DateTime endDateField;
private System.DateTime postedDateField;
private PayrollEmployee[] employeeField;
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(DataType = "date")]
public System.DateTime StartDate
{
get
{
return this.startDateField;
}
set
{
this.startDateField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(DataType = "date")]
public System.DateTime EndDate
{
get
{
return this.endDateField;
}
set
{
this.endDateField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(DataType = "date")]
public System.DateTime PostedDate
{
get
{
return this.postedDateField;
}
set
{
this.postedDateField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute("Employee")]
public PayrollEmployee[] Employee
{
get
{
return this.employeeField;
}
set
{
this.employeeField = value;
}
}
}
/// <remarks/>
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
public partial class PayrollEmployee
{
private string employeePayStatusField;
private string payrollStoreNumberField;
private string reviewedDateField;
private PayrollEmployeePayrollCategory[] payrollCategoryField;
private int employeeIdField;
/// <remarks/>
public string EmployeePayStatus
{
get
{
return this.employeePayStatusField;
}
set
{
this.employeePayStatusField = value;
}
}
/// <remarks/>
public string PayrollStoreNumber
{
get
{
return this.payrollStoreNumberField;
}
set
{
this.payrollStoreNumberField = value;
}
}
/// <remarks/>
public string ReviewedDate
{
get
{
return this.reviewedDateField;
}
set
{
this.reviewedDateField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute("PayrollCategory")]
public PayrollEmployeePayrollCategory[] PayrollCategory
{
get
{
return this.payrollCategoryField;
}
set
{
this.payrollCategoryField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlAttributeAttribute()]
public int EmployeeId
{
get
{
return this.employeeIdField;
}
set
{
this.employeeIdField = value;
}
}
}
/// <remarks/>
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
public partial class PayrollEmployeePayrollCategory
{
private PayrollEmployeePayrollDate[] payrollEmployeePayrollDatesField;
private string categoryField;
/// <remarks/>
[System.Xml.Serialization.XmlAttributeAttribute()]
public string Category
{
get
{
return this.categoryField;
}
set
{
this.categoryField = value;
}
}
[System.Xml.Serialization.XmlElementAttribute("PayrollDate")]
public PayrollEmployeePayrollDate[] PayrollEmployeePayrollDates
{
get
{
return payrollEmployeePayrollDatesField;
}
set
{
payrollEmployeePayrollDatesField = value;
}
}
}
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
public partial class PayrollEmployeePayrollDate
{
private DateTime? paryrollDateField;
private decimal? hours;
private PayrollEmployeePayrollCategoryWorkCode[] payrollEmployeePayrollCategoryWorkCode;
[System.Xml.Serialization.XmlElementAttribute("PayrollDate", typeof(System.DateTime), DataType = "date")]
public DateTime? PayrollDate
{
get
{
return this.paryrollDateField;
}
set
{
this.paryrollDateField = value;
}
}
[System.Xml.Serialization.XmlElementAttribute("Hours", typeof(decimal))]
public decimal? Hours
{
get
{
return this.hours;
}
set
{
this.hours = value;
}
}
[System.Xml.Serialization.XmlElementAttribute("WorkCode", typeof(PayrollEmployeePayrollCategoryWorkCode))]
public PayrollEmployeePayrollCategoryWorkCode[] WorkCode
{
get
{
return payrollEmployeePayrollCategoryWorkCode;
}
set
{
payrollEmployeePayrollCategoryWorkCode = value;
}
}
}
/// <remarks/>
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
public partial class PayrollEmployeePayrollCategoryWorkCode
{
private decimal totalHoursField;
private int codeField;
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute("TotalHours", typeof(decimal))]
public decimal TotalHours
{
get
{
return this.totalHoursField;
}
set
{
this.totalHoursField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlAttributeAttribute()]
public int code
{
get
{
return this.codeField;
}
set
{
this.codeField = value;
}
}
}
}
我更改生成的 classes 的原因是当我循环浏览类别时,我只得到一个日期。正如 XML 所示,每个类别下最多可以有 7 个日期。
XML 来自第三方,我认为我无法让他们更改它。
问题是 XML 结构不再匹配您所拥有的 classes 的结构。
PayrollCategory
的 XML 看起来像这样:
<PayrollCategory Category="REGULAR">
<PayrollDate>2015-02-23</PayrollDate>
<Hours>5.97</Hours>
<WorkCode code="888">
<TotalHours>5.97</TotalHours>
</WorkCode>
<!-- ... -->
请注意,PayrollDate
、Hours
和 WorkCode
元素是 PayrollCategory
的直接子元素。
但是 PayrollEmployeePayrollCategory
的 C# class 结构将所有这三个元素通过类型 PayrollEmployeePayrollDates
属性 移动到子元素 PayrollDate
=22=]。 PayrollEmployeePayrollDate
定义 PayrollDate
、Hours
和 WorkCode
属性(因此也将这些声明为 PayrollDate
的子元素)。
对于您现在拥有的 class 结构,相应的 XML 如下所示:
<PayrollCategory Category="REGULAR">
<PayrollDate>
<PayrollDate>2015-02-23</PayrollDate>
<Hours>5.97</Hours>
<WorkCode code="888">
<TotalHours>5.97</TotalHours>
</WorkCode>
</PayrollDate>
<!-- ... -->
因此,您必须调整 classes 以匹配现有的 XML,或者更改 XML 代以匹配新的 class如果这是你需要的结构。
更新:您无法更新 XML,并且您希望在 C# 中反映 PayrollDate
/Hours
/WorkCode
的分组 classes.
对此没有一个干净的解决方案,因为 .NET XML 序列化框架没有将一组元素映射到 class 的概念,尽管这是一个合理的 XML 习语(在 W3C XML 模式中表示为模型组 xs:group
定义)。
.NET XML 序列化的优点是它很容易做简单的事情,但缺点是它不能很好地扩展到更复杂的用例。
假设我正确理解了您的输入 XML 结构,您可以采取的一种方法是为每个 PayrollDate
、Hours
和 WorkCode
存储数组在映射到 PayrollCategory
的 class 中的 "flat" 表示中。这些将用于 XML 序列化。然后,添加一个 属性,它根据这些 XML 映射的属性计算对象集合,以您想要的方式重组数据:
[System.Xml.Serialization.XmlElementAttribute("PayrollDate", typeof(System.DateTime), DataType = "date")]
public DateTime[] Xml_PayrollDates
{
get;
set;
}
[System.Xml.Serialization.XmlElementAttribute("Hours", typeof(decimal))]
public decimal[] Xml_Hours
{
get;
set;
}
[System.Xml.Serialization.XmlElementAttribute("WorkCode", typeof(PayrollEmployeePayrollCategoryWorkCode))]
public PayrollEmployeePayrollCategoryWorkCode[] Xml_WorkCodes
{
get;
set;
}
[System.Xml.Serialization.XmlIgnore()]
public PayrollEmployeePayrollDate[] PayrollEmployeePayrollDates
{
get
{
if (Xml_PayrollDates == null || Xml_Hours == null || Xml_WorkCodes == null)
{
if (Xml_PayrollDates == null && Xml_Hours == null && Xml_WorkCodes == null)
{
return new PayrollEmployeePayrollDate[0];
}
else
{
throw new ApplicationException("Mismatched PayrollDate/Hours/WorkCode");
}
}
if (Xml_PayrollDates.Length != Xml_WorkCodes.Length || Xml_WorkCodes.Length != Xml_Hours.Length)
{
throw new ApplicationException("Mismatched PayrollDate/Hours/WorkCode");
}
var dates = new PayrollEmployeePayrollDate[Xml_PayrollDates.Length];
for(int i = 0; i < dates.Length; i++)
{
dates[i] = new PayrollEmployeePayrollDate
{
Hours = Xml_Hours[i],
WorkCode = Xml_WorkCodes[i],
PayrollDate = Xml_PayrollDates[i]
};
}
return dates;
}
}
.NET 将按照它们在您的 XML 中出现的顺序对元素进行反序列化,因此如果我正确解释了您的 XML 结构,您可以再次匹配所有内容,因为这些元素总是以相同的顺序出现在组中,并且如果其他元素存在,则组中的三个元素中的每一个都始终存在。这意味着索引 0 处的 Hours
、索引 0 处的 WorkCode
和索引 0 处的 TotalHours
都可以打包到 PayrollEmployeePayrollDate
.[=42 的单个实例中=]
我没有解决通过这个计算 属性 以相同 XML 格式回写的问题,但根据我对您的要求的理解,您只是在读取数据,因此不需要这样做.
这是完整的 classes 集,并进行了必要的调整以支持此方案(请注意 PayrollEmployeePayrollDate
已被修改,并且此 class 不再在XML连载):
/// <remarks/>
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
[System.Xml.Serialization.XmlRootAttribute(Namespace = "", IsNullable = false)]
public class Payroll
{
private System.DateTime startDateField;
private System.DateTime endDateField;
private System.DateTime postedDateField;
private PayrollEmployee[] employeeField;
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(DataType = "date")]
public System.DateTime StartDate
{
get
{
return this.startDateField;
}
set
{
this.startDateField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(DataType = "date")]
public System.DateTime EndDate
{
get
{
return this.endDateField;
}
set
{
this.endDateField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(DataType = "date")]
public System.DateTime PostedDate
{
get
{
return this.postedDateField;
}
set
{
this.postedDateField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute("Employee")]
public PayrollEmployee[] Employee
{
get
{
return this.employeeField;
}
set
{
this.employeeField = value;
}
}
}
/// <remarks/>
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
public partial class PayrollEmployee
{
private string employeePayStatusField;
private string payrollStoreNumberField;
private string reviewedDateField;
private PayrollEmployeePayrollCategory[] payrollCategoryField;
private int employeeIdField;
/// <remarks/>
public string EmployeePayStatus
{
get
{
return this.employeePayStatusField;
}
set
{
this.employeePayStatusField = value;
}
}
/// <remarks/>
public string PayrollStoreNumber
{
get
{
return this.payrollStoreNumberField;
}
set
{
this.payrollStoreNumberField = value;
}
}
/// <remarks/>
public string ReviewedDate
{
get
{
return this.reviewedDateField;
}
set
{
this.reviewedDateField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute("PayrollCategory")]
public PayrollEmployeePayrollCategory[] PayrollCategory
{
get
{
return this.payrollCategoryField;
}
set
{
this.payrollCategoryField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlAttributeAttribute()]
public int EmployeeId
{
get
{
return this.employeeIdField;
}
set
{
this.employeeIdField = value;
}
}
}
/// <remarks/>
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
public partial class PayrollEmployeePayrollCategory
{
private string categoryField;
/// <remarks/>
[System.Xml.Serialization.XmlAttributeAttribute()]
public string Category
{
get
{
return this.categoryField;
}
set
{
this.categoryField = value;
}
}
[System.Xml.Serialization.XmlElementAttribute("PayrollDate", typeof(System.DateTime), DataType = "date")]
public DateTime[] Xml_PayrollDates
{
get;
set;
}
[System.Xml.Serialization.XmlElementAttribute("Hours", typeof(decimal))]
public decimal[] Xml_Hours
{
get;
set;
}
[System.Xml.Serialization.XmlElementAttribute("WorkCode", typeof(PayrollEmployeePayrollCategoryWorkCode))]
public PayrollEmployeePayrollCategoryWorkCode[] Xml_WorkCodes
{
get;
set;
}
[System.Xml.Serialization.XmlIgnore()]
public PayrollEmployeePayrollDate[] PayrollEmployeePayrollDates
{
get
{
if (Xml_PayrollDates == null || Xml_Hours == null || Xml_WorkCodes == null)
{
if (Xml_PayrollDates == null && Xml_Hours == null && Xml_WorkCodes == null)
{
return new PayrollEmployeePayrollDate[0];
}
else
{
throw new ApplicationException("Mismatched PayrollDate/Hours/WorkCode");
}
}
if (Xml_PayrollDates.Length != Xml_WorkCodes.Length || Xml_WorkCodes.Length != Xml_Hours.Length)
{
throw new ApplicationException("Mismatched PayrollDate/Hours/WorkCode");
}
var dates = new PayrollEmployeePayrollDate[Xml_PayrollDates.Length];
for(int i = 0; i < dates.Length; i++)
{
dates[i] = new PayrollEmployeePayrollDate
{
Hours = Xml_Hours[i],
WorkCode = Xml_WorkCodes[i],
PayrollDate = Xml_PayrollDates[i]
};
}
return dates;
}
}
}
public partial class PayrollEmployeePayrollDate
{
public DateTime PayrollDate
{
get;
set;
}
public decimal Hours
{
get;
set;
}
public PayrollEmployeePayrollCategoryWorkCode WorkCode
{
get;
set;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
public partial class PayrollEmployeePayrollCategoryWorkCode
{
private decimal totalHoursField;
private int codeField;
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute("TotalHours", typeof(decimal))]
public decimal TotalHours
{
get
{
return this.totalHoursField;
}
set
{
this.totalHoursField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlAttributeAttribute()]
public int code
{
get
{
return this.codeField;
}
set
{
this.codeField = value;
}
}
}
旁注:如果您使用 List<T>
而不是数组,您可能会发现 classes 更易于使用,并安排集合属性具有空集合的默认值 (所以你不必担心检查 属性 是否为空,如果没有子元素,集合是否为空。
我有以下 XML,我为其自动生成了一个 class。
生成 class 后,我必须进行一些调整才能获得 PayrollEmployeePayrollDate
和 PayrollEmployeePayrollCategoryWorkCode
classes。由于我进行了调整,两个 classes 都已加载,但所有值均为空。除非在反序列化过程中使用它们,否则我不会收到任何错误。为什么我的值没有加载到 class?
<Payroll>
<StartDate>2015-02-22</StartDate>
<EndDate>2015-02-28</EndDate>
<PostedDate>2015-02-28</PostedDate>
<Employee EmployeeId="123456">
<EmployeePayStatus></EmployeePayStatus>
<PayrollStoreNumber>1111</PayrollStoreNumber>
<ReviewedDate></ReviewedDate>
<PayrollCategory Category="OT">
</PayrollCategory>
<PayrollCategory Category="DT">
</PayrollCategory>
<PayrollCategory Category="REGULAR">
<PayrollDate>2015-02-23</PayrollDate>
<Hours>5.97</Hours>
<WorkCode code="888">
<TotalHours>5.97</TotalHours>
</WorkCode>
<PayrollDate>2015-02-24</PayrollDate>
<Hours>6.07</Hours>
<WorkCode code="888">
<TotalHours>6.07</TotalHours>
</WorkCode>
<PayrollDate>2015-02-25</PayrollDate>
<Hours>6.00</Hours>
<WorkCode code="888">
<TotalHours>6.00</TotalHours>
</WorkCode>
<PayrollDate>2015-02-26</PayrollDate>
<Hours>8.44</Hours>
<WorkCode code="888">
<TotalHours>8.44</TotalHours>
</WorkCode>
<PayrollDate>2015-02-27</PayrollDate>
<Hours>7.90</Hours>
<WorkCode code="888">
<TotalHours>7.90</TotalHours>
</WorkCode>
</PayrollCategory>
<PayrollCategory Category="SICK">
</PayrollCategory>
<PayrollCategory Category="VACATION">
</PayrollCategory>
<PayrollCategory Category="HOLIDAY">
</PayrollCategory>
<PayrollCategory Category="RT">
</PayrollCategory>
<PayrollCategory Category="EO">
</PayrollCategory>
<PayrollCategory Category="RSA">
</PayrollCategory>
</Employee>
<Employee EmployeeId="987654">
<EmployeePayStatus></EmployeePayStatus>
<PayrollStoreNumber>1111</PayrollStoreNumber>
<ReviewedDate></ReviewedDate>
<PayrollCategory Category="OT">
</PayrollCategory>
<PayrollCategory Category="DT">
</PayrollCategory>
<PayrollCategory Category="REGULAR">
<PayrollDate>2015-02-23</PayrollDate>
<Hours>6.38</Hours>
<WorkCode code="888">
<TotalHours>6.38</TotalHours>
</WorkCode>
<PayrollDate>2015-02-24</PayrollDate>
<Hours>6.82</Hours>
<WorkCode code="888">
<TotalHours>6.82</TotalHours>
</WorkCode>
<PayrollDate>2015-02-25</PayrollDate>
<Hours>6.83</Hours>
<WorkCode code="888">
<TotalHours>6.83</TotalHours>
</WorkCode>
<PayrollDate>2015-02-26</PayrollDate>
<Hours>7.32</Hours>
<WorkCode code="888">
<TotalHours>7.32</TotalHours>
</WorkCode>
<PayrollDate>2015-02-27</PayrollDate>
<Hours>7.40</Hours>
<WorkCode code="888">
<TotalHours>7.40</TotalHours>
</WorkCode>
<PayrollDate>2015-02-28</PayrollDate>
<Hours>4.17</Hours>
<WorkCode code="888">
<TotalHours>4.17</TotalHours>
</WorkCode>
</PayrollCategory>
<PayrollCategory Category="SICK">
</PayrollCategory>
<PayrollCategory Category="VACATION">
</PayrollCategory>
<PayrollCategory Category="HOLIDAY">
</PayrollCategory>
<PayrollCategory Category="RT">
</PayrollCategory>
<PayrollCategory Category="EO">
</PayrollCategory>
<PayrollCategory Category="RSA">
</PayrollCategory>
</Employee>
</Payroll>
这是我正在使用的 class。
namespace PayrollProcessor.BL
{
/// <remarks/>
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
[System.Xml.Serialization.XmlRootAttribute(Namespace = "", IsNullable = false)]
public class Payroll
{
private System.DateTime startDateField;
private System.DateTime endDateField;
private System.DateTime postedDateField;
private PayrollEmployee[] employeeField;
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(DataType = "date")]
public System.DateTime StartDate
{
get
{
return this.startDateField;
}
set
{
this.startDateField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(DataType = "date")]
public System.DateTime EndDate
{
get
{
return this.endDateField;
}
set
{
this.endDateField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(DataType = "date")]
public System.DateTime PostedDate
{
get
{
return this.postedDateField;
}
set
{
this.postedDateField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute("Employee")]
public PayrollEmployee[] Employee
{
get
{
return this.employeeField;
}
set
{
this.employeeField = value;
}
}
}
/// <remarks/>
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
public partial class PayrollEmployee
{
private string employeePayStatusField;
private string payrollStoreNumberField;
private string reviewedDateField;
private PayrollEmployeePayrollCategory[] payrollCategoryField;
private int employeeIdField;
/// <remarks/>
public string EmployeePayStatus
{
get
{
return this.employeePayStatusField;
}
set
{
this.employeePayStatusField = value;
}
}
/// <remarks/>
public string PayrollStoreNumber
{
get
{
return this.payrollStoreNumberField;
}
set
{
this.payrollStoreNumberField = value;
}
}
/// <remarks/>
public string ReviewedDate
{
get
{
return this.reviewedDateField;
}
set
{
this.reviewedDateField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute("PayrollCategory")]
public PayrollEmployeePayrollCategory[] PayrollCategory
{
get
{
return this.payrollCategoryField;
}
set
{
this.payrollCategoryField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlAttributeAttribute()]
public int EmployeeId
{
get
{
return this.employeeIdField;
}
set
{
this.employeeIdField = value;
}
}
}
/// <remarks/>
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
public partial class PayrollEmployeePayrollCategory
{
private PayrollEmployeePayrollDate[] payrollEmployeePayrollDatesField;
private string categoryField;
/// <remarks/>
[System.Xml.Serialization.XmlAttributeAttribute()]
public string Category
{
get
{
return this.categoryField;
}
set
{
this.categoryField = value;
}
}
[System.Xml.Serialization.XmlElementAttribute("PayrollDate")]
public PayrollEmployeePayrollDate[] PayrollEmployeePayrollDates
{
get
{
return payrollEmployeePayrollDatesField;
}
set
{
payrollEmployeePayrollDatesField = value;
}
}
}
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
public partial class PayrollEmployeePayrollDate
{
private DateTime? paryrollDateField;
private decimal? hours;
private PayrollEmployeePayrollCategoryWorkCode[] payrollEmployeePayrollCategoryWorkCode;
[System.Xml.Serialization.XmlElementAttribute("PayrollDate", typeof(System.DateTime), DataType = "date")]
public DateTime? PayrollDate
{
get
{
return this.paryrollDateField;
}
set
{
this.paryrollDateField = value;
}
}
[System.Xml.Serialization.XmlElementAttribute("Hours", typeof(decimal))]
public decimal? Hours
{
get
{
return this.hours;
}
set
{
this.hours = value;
}
}
[System.Xml.Serialization.XmlElementAttribute("WorkCode", typeof(PayrollEmployeePayrollCategoryWorkCode))]
public PayrollEmployeePayrollCategoryWorkCode[] WorkCode
{
get
{
return payrollEmployeePayrollCategoryWorkCode;
}
set
{
payrollEmployeePayrollCategoryWorkCode = value;
}
}
}
/// <remarks/>
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
public partial class PayrollEmployeePayrollCategoryWorkCode
{
private decimal totalHoursField;
private int codeField;
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute("TotalHours", typeof(decimal))]
public decimal TotalHours
{
get
{
return this.totalHoursField;
}
set
{
this.totalHoursField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlAttributeAttribute()]
public int code
{
get
{
return this.codeField;
}
set
{
this.codeField = value;
}
}
}
}
我更改生成的 classes 的原因是当我循环浏览类别时,我只得到一个日期。正如 XML 所示,每个类别下最多可以有 7 个日期。
XML 来自第三方,我认为我无法让他们更改它。
问题是 XML 结构不再匹配您所拥有的 classes 的结构。
PayrollCategory
的 XML 看起来像这样:
<PayrollCategory Category="REGULAR">
<PayrollDate>2015-02-23</PayrollDate>
<Hours>5.97</Hours>
<WorkCode code="888">
<TotalHours>5.97</TotalHours>
</WorkCode>
<!-- ... -->
请注意,PayrollDate
、Hours
和 WorkCode
元素是 PayrollCategory
的直接子元素。
但是 PayrollEmployeePayrollCategory
的 C# class 结构将所有这三个元素通过类型 PayrollEmployeePayrollDates
属性 移动到子元素 PayrollDate
=22=]。 PayrollEmployeePayrollDate
定义 PayrollDate
、Hours
和 WorkCode
属性(因此也将这些声明为 PayrollDate
的子元素)。
对于您现在拥有的 class 结构,相应的 XML 如下所示:
<PayrollCategory Category="REGULAR">
<PayrollDate>
<PayrollDate>2015-02-23</PayrollDate>
<Hours>5.97</Hours>
<WorkCode code="888">
<TotalHours>5.97</TotalHours>
</WorkCode>
</PayrollDate>
<!-- ... -->
因此,您必须调整 classes 以匹配现有的 XML,或者更改 XML 代以匹配新的 class如果这是你需要的结构。
更新:您无法更新 XML,并且您希望在 C# 中反映 PayrollDate
/Hours
/WorkCode
的分组 classes.
对此没有一个干净的解决方案,因为 .NET XML 序列化框架没有将一组元素映射到 class 的概念,尽管这是一个合理的 XML 习语(在 W3C XML 模式中表示为模型组 xs:group
定义)。
.NET XML 序列化的优点是它很容易做简单的事情,但缺点是它不能很好地扩展到更复杂的用例。
假设我正确理解了您的输入 XML 结构,您可以采取的一种方法是为每个 PayrollDate
、Hours
和 WorkCode
存储数组在映射到 PayrollCategory
的 class 中的 "flat" 表示中。这些将用于 XML 序列化。然后,添加一个 属性,它根据这些 XML 映射的属性计算对象集合,以您想要的方式重组数据:
[System.Xml.Serialization.XmlElementAttribute("PayrollDate", typeof(System.DateTime), DataType = "date")]
public DateTime[] Xml_PayrollDates
{
get;
set;
}
[System.Xml.Serialization.XmlElementAttribute("Hours", typeof(decimal))]
public decimal[] Xml_Hours
{
get;
set;
}
[System.Xml.Serialization.XmlElementAttribute("WorkCode", typeof(PayrollEmployeePayrollCategoryWorkCode))]
public PayrollEmployeePayrollCategoryWorkCode[] Xml_WorkCodes
{
get;
set;
}
[System.Xml.Serialization.XmlIgnore()]
public PayrollEmployeePayrollDate[] PayrollEmployeePayrollDates
{
get
{
if (Xml_PayrollDates == null || Xml_Hours == null || Xml_WorkCodes == null)
{
if (Xml_PayrollDates == null && Xml_Hours == null && Xml_WorkCodes == null)
{
return new PayrollEmployeePayrollDate[0];
}
else
{
throw new ApplicationException("Mismatched PayrollDate/Hours/WorkCode");
}
}
if (Xml_PayrollDates.Length != Xml_WorkCodes.Length || Xml_WorkCodes.Length != Xml_Hours.Length)
{
throw new ApplicationException("Mismatched PayrollDate/Hours/WorkCode");
}
var dates = new PayrollEmployeePayrollDate[Xml_PayrollDates.Length];
for(int i = 0; i < dates.Length; i++)
{
dates[i] = new PayrollEmployeePayrollDate
{
Hours = Xml_Hours[i],
WorkCode = Xml_WorkCodes[i],
PayrollDate = Xml_PayrollDates[i]
};
}
return dates;
}
}
.NET 将按照它们在您的 XML 中出现的顺序对元素进行反序列化,因此如果我正确解释了您的 XML 结构,您可以再次匹配所有内容,因为这些元素总是以相同的顺序出现在组中,并且如果其他元素存在,则组中的三个元素中的每一个都始终存在。这意味着索引 0 处的 Hours
、索引 0 处的 WorkCode
和索引 0 处的 TotalHours
都可以打包到 PayrollEmployeePayrollDate
.[=42 的单个实例中=]
我没有解决通过这个计算 属性 以相同 XML 格式回写的问题,但根据我对您的要求的理解,您只是在读取数据,因此不需要这样做.
这是完整的 classes 集,并进行了必要的调整以支持此方案(请注意 PayrollEmployeePayrollDate
已被修改,并且此 class 不再在XML连载):
/// <remarks/>
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
[System.Xml.Serialization.XmlRootAttribute(Namespace = "", IsNullable = false)]
public class Payroll
{
private System.DateTime startDateField;
private System.DateTime endDateField;
private System.DateTime postedDateField;
private PayrollEmployee[] employeeField;
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(DataType = "date")]
public System.DateTime StartDate
{
get
{
return this.startDateField;
}
set
{
this.startDateField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(DataType = "date")]
public System.DateTime EndDate
{
get
{
return this.endDateField;
}
set
{
this.endDateField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(DataType = "date")]
public System.DateTime PostedDate
{
get
{
return this.postedDateField;
}
set
{
this.postedDateField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute("Employee")]
public PayrollEmployee[] Employee
{
get
{
return this.employeeField;
}
set
{
this.employeeField = value;
}
}
}
/// <remarks/>
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
public partial class PayrollEmployee
{
private string employeePayStatusField;
private string payrollStoreNumberField;
private string reviewedDateField;
private PayrollEmployeePayrollCategory[] payrollCategoryField;
private int employeeIdField;
/// <remarks/>
public string EmployeePayStatus
{
get
{
return this.employeePayStatusField;
}
set
{
this.employeePayStatusField = value;
}
}
/// <remarks/>
public string PayrollStoreNumber
{
get
{
return this.payrollStoreNumberField;
}
set
{
this.payrollStoreNumberField = value;
}
}
/// <remarks/>
public string ReviewedDate
{
get
{
return this.reviewedDateField;
}
set
{
this.reviewedDateField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute("PayrollCategory")]
public PayrollEmployeePayrollCategory[] PayrollCategory
{
get
{
return this.payrollCategoryField;
}
set
{
this.payrollCategoryField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlAttributeAttribute()]
public int EmployeeId
{
get
{
return this.employeeIdField;
}
set
{
this.employeeIdField = value;
}
}
}
/// <remarks/>
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
public partial class PayrollEmployeePayrollCategory
{
private string categoryField;
/// <remarks/>
[System.Xml.Serialization.XmlAttributeAttribute()]
public string Category
{
get
{
return this.categoryField;
}
set
{
this.categoryField = value;
}
}
[System.Xml.Serialization.XmlElementAttribute("PayrollDate", typeof(System.DateTime), DataType = "date")]
public DateTime[] Xml_PayrollDates
{
get;
set;
}
[System.Xml.Serialization.XmlElementAttribute("Hours", typeof(decimal))]
public decimal[] Xml_Hours
{
get;
set;
}
[System.Xml.Serialization.XmlElementAttribute("WorkCode", typeof(PayrollEmployeePayrollCategoryWorkCode))]
public PayrollEmployeePayrollCategoryWorkCode[] Xml_WorkCodes
{
get;
set;
}
[System.Xml.Serialization.XmlIgnore()]
public PayrollEmployeePayrollDate[] PayrollEmployeePayrollDates
{
get
{
if (Xml_PayrollDates == null || Xml_Hours == null || Xml_WorkCodes == null)
{
if (Xml_PayrollDates == null && Xml_Hours == null && Xml_WorkCodes == null)
{
return new PayrollEmployeePayrollDate[0];
}
else
{
throw new ApplicationException("Mismatched PayrollDate/Hours/WorkCode");
}
}
if (Xml_PayrollDates.Length != Xml_WorkCodes.Length || Xml_WorkCodes.Length != Xml_Hours.Length)
{
throw new ApplicationException("Mismatched PayrollDate/Hours/WorkCode");
}
var dates = new PayrollEmployeePayrollDate[Xml_PayrollDates.Length];
for(int i = 0; i < dates.Length; i++)
{
dates[i] = new PayrollEmployeePayrollDate
{
Hours = Xml_Hours[i],
WorkCode = Xml_WorkCodes[i],
PayrollDate = Xml_PayrollDates[i]
};
}
return dates;
}
}
}
public partial class PayrollEmployeePayrollDate
{
public DateTime PayrollDate
{
get;
set;
}
public decimal Hours
{
get;
set;
}
public PayrollEmployeePayrollCategoryWorkCode WorkCode
{
get;
set;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
public partial class PayrollEmployeePayrollCategoryWorkCode
{
private decimal totalHoursField;
private int codeField;
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute("TotalHours", typeof(decimal))]
public decimal TotalHours
{
get
{
return this.totalHoursField;
}
set
{
this.totalHoursField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlAttributeAttribute()]
public int code
{
get
{
return this.codeField;
}
set
{
this.codeField = value;
}
}
}
旁注:如果您使用 List<T>
而不是数组,您可能会发现 classes 更易于使用,并安排集合属性具有空集合的默认值 (所以你不必担心检查 属性 是否为空,如果没有子元素,集合是否为空。