At least with the standard .Net XMLSerializer there's no way to decorate your class with attributes to get the serialization working as you would like. But you could work around that using a class structure like this:
public class InvoiceList {
[XmlElement("document")]
public Invoice[] Invoices { get; set; }
}
public class Invoice {
[XmlIgnore]
public string InvoiceId => this.PropertyValues.First(p => p.Name == "InvoiceID").Value;
[XmlIgnore]
public string CompanyName => this.PropertyValues.First(p => p.Name == "CompanyName").Value;
[XmlIgnore]
public string VendorName => this.PropertyValues.First(p => p.Name == "VendorName").Value;
[XmlIgnore]
public decimal GrossAmt => decimal.Parse(this.PropertyValues.First(p => p.Name == "GrossAmt").Value);
[XmlIgnore]
public DateTime InvoiceDate => DateTime.Parse(this.PropertyValues.First(p => p.Name == "InvoiceDate").Value);
[XmlArray("propertyValues")]
[XmlArrayItem("propertyValue")]
public PropertyValue[] PropertyValues { get; set; }
}
public class PropertyValue {
[XmlElement("name")]
public string Name { get; set; }
[XmlElement("value")]
public string Value { get; set; }
}
The Invoice class would still look the same (at least for reading, writing needs a little bit more work, but I hope you get the idea). For sure there needs to be some more meaningful error handling.
The xml string would need to be wrapped in an <InvoiceList>...</InvoiceList>
tag for this to work:
<?xml version="1.0" encoding="UTF-8"?>
<InvoiceList>
<document name="doc1.pdf">
<propertyValues>
<propertyValue><name>InvoiceID</name><value>123</value></propertyValue>
<propertyValue><name>CompanyName</name><value>Company1</value></propertyValue>
<propertyValue><name>VendorName</name><value>Vendor1</value></propertyValue>
<propertyValue><name>GrossAmt</name><value>176.33</value></propertyValue>
<propertyValue><name>InvoiceDate</name><value>26-03-2019</value></propertyValue>
</propertyValues>
</document>
<document name="doc2.pdf">
<propertyValues>
<propertyValue><name>InvoiceID</name><value>223</value></propertyValue>
<propertyValue><name>CompanyName</name><value>Company2</value></propertyValue>
<propertyValue><name>VendorName</name><value>Vendor2</value></propertyValue>
<propertyValue><name>GrossAmt</name><value>5300.88</value></propertyValue>
<propertyValue><name>InvoiceDate</name><value>31-03-2019</value></propertyValue>
</propertyValues>
</document>
</InvoiceList>
The deserialization itself:
var xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><InvoiceList><document name=\"doc1.pdf\"><propertyValues><propertyValue><name>InvoiceID</name><value>123</value></propertyValue><propertyValue><name>CompanyName</name><value>Company1</value></propertyValue><propertyValue><name>VendorName</name><value>Vendor1</value></propertyValue><propertyValue><name>GrossAmt</name><value>176.33</value></propertyValue><propertyValue><name>InvoiceDate</name><value>26-03-2019</value></propertyValue></propertyValues></document><document name=\"doc2.pdf\"><propertyValues><propertyValue><name>InvoiceID</name><value>223</value></propertyValue><propertyValue><name>CompanyName</name><value>Company2</value></propertyValue><propertyValue><name>VendorName</name><value>Vendor2</value></propertyValue><propertyValue><name>GrossAmt</name><value>5300.88</value></propertyValue><propertyValue><name>InvoiceDate</name><value>31-03-2019</value></propertyValue></propertyValues></document></InvoiceList>";
using var stream = new MemoryStream();
using var writer = new StreamWriter(stream);
writer.Write(xml);
writer.Flush();
stream.Position = 0;
using var serializer = new XmlSerializer(typeof(InvoiceList));
var list = (InvoiceList)serializer.Deserialize(stream);
foreach (var i in list.Invoices) {
Console.WriteLine($"{i.InvoiceId}, {i.CompanyName}");
}