parliament
parliament

Reputation: 22914

Conditional Query with LINQ to XML

Im using LINQ to XML to delete and inserts tags into an xml document. One situation I often encounter is that I have a preference of where I want to insert a particular tag but that preference can't always be met. For example here I'd prefer to insert it right after the last element with the same CalendarCode:

elements = from e in calendarDocument.Descendants("ExceptionalSessions") where e.Element("CalendarCode") == calendarCode select e;

elements.Last().AddAfterSelf(sessionElement);

However sometimes the element to be inserted is the first of its kind in that document with that CalendarCode so the extra condition:

where e.Element("CalendarCode") == calendarCode  

will create an empty result set. In that case I'd like to use a query without that additional condition. This is a one time thing though, after inserting an element with that calendar code I'd like the NEXT element with the same CalendarCode to be inserted after the first one... in that case I'd want to use the query with that additional condition.

I tried a few ways to solve this but they all look very crude and possibly inefficient and I couldnt help but think there's a better way.

Can anyone give me an idea if they ever encountered this.

Upvotes: 1

Views: 399

Answers (1)

Pablo Romeo
Pablo Romeo

Reputation: 11396

One option is to evaluate the condition and decide the target prior to adding it. Using a separate method for clarity, possibly something like this (not tested):

private XElement GetCalendarTargetNode(XElement source, XElement calendarCode)
        {
            var exceptionalSessions = source.Descendants("ExceptionalSessions");
            return exceptionalSessions.LastOrDefault(e => e.Element("CalendarCode") == calendarCode) ?? exceptionalSessions.Last();
        }

Or a slightly different implementation:

private XElement GetCalendarTargetNode(XElement source, XElement calendarCode)
        {
            var exceptionalSessions = source.Descendants("ExceptionalSessions");
            return exceptionalSessions.Where(e => e.Element("CalendarCode") == calendarCode).DefaultIfEmpty(exceptionalSessions.Last()).Last();
        }

And use it:

var target = GetCalendarTargetNode(calendarDocument, calendarCode);
target.AddAfterSelf(sessionElement);

EDIT: Or a simplified version without using extra methods:

    var exceptionalSessions = calendarDocument.Descendants("ExceptionalSessions");
    var target = exceptionalSessions.Where(e => e.Element("CalendarCode") == calendarCode)
        .DefaultIfEmpty(exceptionalSessions.Last());
    target.Last().AddAfterSelf(sessionElement);

Upvotes: 2

Related Questions