我需要创建/读取xml文件。我得到了一个.xsd文件,并生成了.cs类。序列化和反序列化工作。当我创建文件时,我只是将值添加到Items数组,然后键入ItemsItemName数组。
问题在于阅读。在类中,没有诸如Date,Header等之类的属性,但是只有一个数组用于存储对象,第二个数组用于存储类型。
通常,当我需要读取xml文件时,我会对它进行反序列化并获取其中包含对象的实例,但是在这种情况下,它并不是那么简单。我只有一个充满值的数组,很难获得我需要的值。
public partial class Invoice
{
private object[] itemsField;
public Invoice()
{
}
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute("Dates", typeof(Dates))]
[System.Xml.Serialization.XmlElementAttribute("Header", typeof(Header))]
[System.Xml.Serialization.XmlElementAttribute("CompanyData", typeof(CompanyData))]
[System.Xml.Serialization.XmlElementAttribute("TextDescription", typeof(TextDescription))]
[System.Xml.Serialization.XmlElementAttribute("InvoiceItems", typeof(InvoiceItems))]
[System.Xml.Serialization.XmlChoiceIdentifierAttribute("ItemsElementName")]
public object[] Items
{
get
{
return this.itemsField;
}
set
{
this.itemsField = value;
}
}
[System.Xml.Serialization.XmlElementAttribute("ItemsElementName")]
[System.Xml.Serialization.XmlIgnoreAttribute()]
public ItemsChoiceType1[] ItemsElementName
{
get
{
return this.itemsElementNameField;
}
set
{
this.itemsElementNameField = value;
}
}
// etc ...
}
类头同样具有一个用于值的数组,以及一个用于类型的数组(类型可以是字符串,用户可以定义为InvoiceType ...)。
目前,我尝试了两种解决方案。首先,我反序列化xml文件并遍历Items数组。但这并不是那么简单,因为在一个数组中我有值,在第二个数组中有类型。
其次,我远离反序列化,使用了XDocument并获得了我需要的值。
有更好的解决方案吗?
最佳答案
您可以手动定义类,例如
public partial class Invoice
{
public Invoice()
{
}
[XmlElement("Dates")]
public List<Dates> Dates { get; set; }
// and so on.
}
其实并不难,只需几分钟,您就可以完成操作,并且可以通过
XmlSerializer
以更方便的方式对它们进行反序列化了。另外,您可以使用Lambda表达式+扩展方法来选择所需的信息,例如:
public static class InvoiceExtensions
{
public static IEnumerable<Dates> Dates(this Invoice invoice)
{
return invoice.Items.OfType<Dates>();
}
}
Items
表中的对象实际上是预期的类型,您只需要过滤掉它们即可。真正需要使用ItemsElementName
的唯一时间是当不同的选择(即不同的XML元素名称)映射到相同的数据类型时,并且您需要知道是哪个。在这种情况下,可以使用Enumerable.Zip将它们放在一起:public static class InvoiceExtensions
{
public static IEnumerable<KeyValuePair<ItemsChoiceType1, object>> ElementNamesAndItems<T>(this Invoice invoice)
{
return invoice.ItemsElementName.Zip(invoice.Items, (choice, item) => new KeyValuePair<ItemsChoiceType1, object>(choice, item)).Where(p => p.Value is T);
}
}
然后稍后过滤它们:
var relevantDates = invoice.ElementNamesAndItems<Dates>().Where(p => p.Key == ItemsChoiceType1.StartDate).Select(p => p.Value);
在您的情况下,这可能不是必需的,因为您的选择似乎都对应于一个不同的类。