0

first time poster, long time reader. I've got an XML import to write (another first), and i'm getting lost in the conflicting methods and approaches that can be adopted.

The XML I'm trying to Import looks roughly like this:

...
<TableRow>
    <Field Name="DeliveryNote" Type="etc..">Text</Field>
    <Field Name="OrderNumber" Type="etc..">Text</Field>
    and so on...
</TableRow>
...

I have an object with Properties for the majority of the fields (not all required), and I'm currently populating the properties in a constructor that is thrown the relevant XElement to build from, like so:

public Order(XElement p_tableRow)
{
foreach (XElement field in p_TableRow.Elements("Field"))
    {
        switch (field.Attribute("Name").Value)
        {
            case "DeliveryNote":
                ReasonCode = field.Value;
                break;
            case "OrderNumber":
                OrderID = field.Value;
                break;
            case "ProductCode":
                CustProductCode = field.Value;
                break;
            case "Quantity":
                QuantityCharged = field.Value;
                break;
...

My problem is that whilst this gets the job done, it seems awfully clunky (and ugly). Surely there is a better way?

I've tried getting my head around how to do this with projection but haven't found an example where you're deciding the destination of the data based on an attribute in the node.

I'm using .NET 3.5

Any pointers would be massively appreciated.

AshLewis
  • 3
  • 3
  • Have you tried using Xml Serialization? http://stackoverflow.com/questions/16831317/c-sharp-xml-deserialization-xmlattribute – Sam.C Jun 02 '16 at 21:33
  • I like your code. It is easy to understand and modify. You are creating a Pivot Table and Pivot table code can be complex. I would keep the code as simple as possible and not to look for any shortcuts. – jdweng Jun 02 '16 at 21:59
  • 1
    @Sam.C: I'm not sure Serialisation is the right way to go here, because technically (as far as i understand it) I'd have to much about creating a field class to deserialise into, just essentially to get a key/value pair. – AshLewis Jun 02 '16 at 22:32
  • @jdweng: glad you like it, but I'm a little worried that the performance is going to be lousy compared to some of the voodoo i see going on elsewhere, but don't understand. :) – AshLewis Jun 02 '16 at 22:36
  • If the xml is small I wouldn't worry about performance. Performance is only issue with large xml and then you should use XmlReader. – jdweng Jun 02 '16 at 23:01
  • @AshLewis you are correct! I take it back, serialization is not gonna work here. your code looks good. the answer by itsme86 looks easy to scale as you add more columns to your mapping. – Sam.C Jun 03 '16 at 00:10

1 Answers1

1

You could do some mapping and rely on reflection:

private Dictionary<string, string> _mapping = new Dictionary<string, string>
{
    { "DeliveryNote", "ReasonCode" },
    { "OrderNumber",  "OrderID" },
    { "ProductCode",  "CustProductCode" },
    { "Quantity",     "QuantityCharged" }
};

Then your import would just look something like this:

public Order(XElement p_tableRow)
{
    foreach (XElement field in p_TableRow.Elements("Field"))
    {
        string propName = _mapping[field.Attribute("Name").Value];
        PropertyInfo propInfo = GetType().GetProperty(propName);
        propInfo.SetValue(this, field.Value);
    }
}

Then you'd never have to update your Order() method again and can just add new attribute/property pairs to the mapping.

itsme86
  • 19,266
  • 4
  • 41
  • 57
  • I like the scalability here, great answer. would the same (dictionary-driven) approach be achievable using something like XPaths? the reason I ask is i have another class in the same project that draws on various elements from under the root. – AshLewis Jun 03 '16 at 08:42