0

In my code, I have got an Flags Enum for days of the week, as follows:

[Flags]
public enum DaysOfWeek          // enumeration for days of week
{
    Sunday = 0x0000001,
    Saturday = 0x0000010,
    Friday = 0x0000100,
    Thursday = 0x0001000,
    Wednesday = 0x0010000,
    Tuesday = 0x0100000,
    Monday = 0x1000000,
    MondayToFriday = Monday | Tuesday | Wednesday | Thursday | Friday,
    MondayToSaturday = MondayToFriday | Saturday,
    NotSaturday = MondayToFriday | Sunday,
    Weekend = Saturday | Sunday,
    MondayToSunday = MondayToFriday | Weekend,
    HolidaysOnly = ~MondayToSunday,
}

And I use this as in the following simplified example to output XML:

List<DaysOfWeek> profiles = new List<DaysOfWeek>();
profiles.Add(DaysOfWeek.MondayToFriday);
profiles.Add(DaysOfWeek.MondayToSaturday);
profiles.Add(DaysOfWeek.Monday | DaysOfWeek.Tuesday);

XElement xml = new XElement("Profiles",
                 from DaysOfWeek pf in profiles 
                 select new XElement("Profile",pf.ToString())
               );
Console.WriteLine(xml);

This gives me the output:

<Profiles>
    <Profile>MondayToFriday</Profile>
    <Profile>MondayToSaturday</Profile>
    <Profile>Tuesday, Monday</Profile>
</Profiles>

But what I want is:

<Profiles>
    <Profile>
        <MondayToFriday />
    </Profile
    <Profile>
        <MondayToSaturday />
    </Profile>
    <Profile>
        <Monday />
        <Tuesday />
    </Profile>
</Profiles>

I appreciate that the format of my XElement needs to be extended so that I get empty elements for the days of the week, but if I do this then the "Tuesday, Monday" element throws an exception because I can't use a comma (or space) as part of an element name.

But

a) If not using one of the predefined groups of days, I need to write the elements in a particular order (Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday) which is given by the schema (see c below). I have made it harder for myself because I've defined them in reverse, with Monday as the high bit, but this was because the older data format that I dealt with first presents the days as flags (1/0) in a string in that order e.g. Monday and Tuesday are "1100000" (Monday on left, Sunday on right);

b) I would like to be able to output the appropriate elements without having to test for everything individually (although I guess I will have to if I have to); and

c) The output XML format I am looking for is dictated by a standard with an XSD, and I can't change it.

Any bright ideas?

StuartR143
  • 369
  • 2
  • 10
  • Thanks for the edit @MUG4N. Not quite sure where that initial [ went, because it was in the code that I originally copied! – StuartR143 Mar 15 '17 at 16:21

1 Answers1

0

The following might suit your needs.
It parses the output string of the flag and determines if the content should be an XElement or a list of.

public static object GetDaysOfWeekXelementContent(DaysOfWeek pf)
{
    var pfStr = pf.ToString();
    if (pfStr.Contains(","))
    {
        return pfStr.Split(',').Select(x => new XElement(x.Trim()));
    }
    else
    {
        return new XElement(pfStr);
    }
}

static void Main(string[] args)
{
    List<DaysOfWeek> profiles = new List<DaysOfWeek>();
    profiles.Add(DaysOfWeek.MondayToFriday);
    profiles.Add(DaysOfWeek.MondayToSaturday);
    profiles.Add(DaysOfWeek.Monday | DaysOfWeek.Tuesday);

    XElement xml = new XElement("Profiles",
                        from DaysOfWeek pf in profiles
                        select new XElement("Profile", GetDaysOfWeekXelementContent(pf))
                    );
    Console.WriteLine(xml);
}

Edit Regarding sorting of the values, you declare your values from Sunday to Monday. You can parse the values one by one, sort them descending in order to have Monday to Sunday.
The following should do:

public static object GetDaysOfWeekXelementContent(DaysOfWeek pf)
{
    var pfStr = pf.ToString();
    if (pfStr.Contains(","))
    {
        return pfStr.Split(',').Reverse().Select(x => new XElement(x.Trim()));
    }
    else
    {
        return new XElement(pfStr);
    }
}
StfBln
  • 1,137
  • 6
  • 11
  • It seems a reasonable approach. If I use `return pfStr.Split(',').Reverse().Select(x => new XElement(x.Trim()));` that should also solve the reversed days of the week issue? – StuartR143 Mar 15 '17 at 16:36
  • @StuartR143 are you looking to have the days ordered alphabetically or via the Enum value? – StfBln Mar 15 '17 at 16:39
  • @StfBIn I've edited (a) in my original question to explain more fully what I want and why – StuartR143 Mar 15 '17 at 16:50
  • @StfBIn That looks more complicated than just using `Reverse()`, and also less readable as to what it is actually doing. Are there performance issues that mean I shouldn't, or ...? – StuartR143 Mar 15 '17 at 16:55
  • @StuartR143 if you sort alphabetically, Friday will come before Monday. Since you have defined your values via the enum, better to use them that way, at least you can predict the outcome. – StfBln Mar 15 '17 at 16:57
  • @StfBIn but `Reverse()` isn't sorting alphabetically. I have tried your original code, but with my suggested `Reverse()` in there, and it seems to work correctly for all the different combinations I have thrown at it (although I have also defined some additional 6-day groups that are in the schema that I had left out) – StuartR143 Mar 15 '17 at 17:18
  • @StuartR143 Oh, I see. I have updated the answer in order to reflect the accepted solution. – StfBln Mar 15 '17 at 17:32