我有以下XML,我自动生成了一个类。
生成课程后,我必须进行一些调整才能获得PayrollEmployeePayrollDate
和PayrollEmployeePayrollCategoryWorkCode
课程。由于我进行了调整,因此加载了两个类,但所有值都为null。除非在反序列化过程中被消耗,否则我不会收到任何错误。为什么我的值没有加载到类中?
<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>
这是我正在上课的课程。
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;
}
}
}
}
我更改生成的类的原因是因为当我遍历类别时,我只有一个日期。正如XML所示,每个类别下最多可以有7个日期。
XML来自第三方,我不认为我可以让他们改变它。
答案 0 :(得分:1)
问题是XML结构不再匹配您所拥有的类的结构。
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#类结构通过PayrollDate
类型的PayrollEmployeePayrollDates
属性将所有这三个元素移动到子元素PayrollEmployeePayrollDate[]
中。 PayrollEmployeePayrollDate
定义了PayrollDate
,Hours
和WorkCode
属性(因此也将这些属性声明为PayrollDate
的子元素。)
对于您现在拥有的类结构,相应的XML将如下所示:
<PayrollCategory Category="REGULAR">
<PayrollDate>
<PayrollDate>2015-02-23</PayrollDate>
<Hours>5.97</Hours>
<WorkCode code="888">
<TotalHours>5.97</TotalHours>
</WorkCode>
</PayrollDate>
<!-- ... -->
因此,您必须调整您的类以匹配您拥有的XML,或者更改您的XML生成以匹配新的类结构(如果这是您需要的。)
更新:您无法更新XML,并希望在C#类中反映出PayrollDate
/ Hours
/ WorkCode
的分组。
没有一个干净的解决方案,因为.NET XML序列化框架没有将一组元素映射到类的概念,即使这是一个合理的XML习惯用法(如下所示) W3C XML Schema作为模型组xs:group
定义。)
.NET XML序列化的优点在于它很容易做到这一点,但缺点是它不能很好地扩展到更复杂的用例。
假设我正确理解您的输入XML结构,您可以采取的方法是以“平面”表示形式为PayrollDate
,Hours
和WorkCode
中的每一个存储数组在您的课程内,映射到PayrollCategory
。这些将用于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;
}
}
元素将按照它们在XML中出现的顺序进行反序列化,因此,如果我正确地解释您的XML结构,您可以再次匹配所有内容,因为这些元素总是以相同的顺序出现在如果其他元素存在,则组中的每个元素始终存在。这意味着索引0处的Hours
,索引0处的WorkCode
和索引0处的TotalHours
都可以打包到PayrollEmployeePayrollDate
的单个实例中。
我没有通过这个计算属性以相同的XML格式写回来,但是根据我对你的要求的理解,你只是在阅读数据,所以这不是必需的。
这是完整的类集,需要进行必要的调整以支持此方案(请注意PayrollEmployeePayrollDate
已被修改,此类不再参与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>
而不是数组,您可能会发现您的类更容易使用,并且安排集合属性的默认值为空集合(因此您不必担心检查两个属性是否为空,如果没有子元素,则集合为空。)