Is this possible to achieve with LINQ to XML?
I have a List<Congregation>
object and I obtain a list of all items where the last invited date is older than today:
var congs =_CongregationData.Congregations
.Where(a => a.LastInvited < DateTime.Today)
That's step 1. But then I have another XML file. Here is a cut down sample (ignore the dates as they are made up):
<AssignmentHistory>
<W20230731>
<PublicTalkInfo>
<PublicTalkTheme>Theme 1</PublicTalkTheme>
</PublicTalkInfo>
</W20230731>
<W20230807>
<PublicTalkInfo>
<PublicTalkTheme>Theme 2</PublicTalkTheme>
</PublicTalkInfo>
</W20230807>
<W20230814>
<PublicTalkInfo>
<MeetingDate>2023-08-20</MeetingDate>
<PublicTalkCongregation>Congregation 1</PublicTalkCongregation>
<PublicTalkTheme>Theme 3</PublicTalkTheme>
</PublicTalkInfo>
</W20230814>
<W20230821>
<PublicTalkInfo>
<MeetingDate>2023-08-27</MeetingDate>
<PublicTalkCongregation>Congregation 2</PublicTalkCongregation>
<PublicTalkTheme>Theme 4</PublicTalkTheme>
</PublicTalkInfo>
</W20230821>
<W20230828>
<PublicTalkInfo>
<MeetingDate>2023-09-03</MeetingDate>
<PublicTalkCongregation>Congregation 3</PublicTalkCongregation>
<PublicTalkTheme>Theme 5</PublicTalkTheme>
</PublicTalkInfo>
</W20230828>
</AssignmentHistory>
I know that this XML is badly designed (with the WYYYYMMDD
nodes all having different names) but this is the data file I must work with. Can I use LINQ to XML to obtain a set of records from this XML.
Eg,
for(var cong : congs)
{
// 1. Select from history XML all records where PublicTalkCongregation is cong.Name.
// 2. Records must be date descending on MeetingDate.
// 3. We only want the records older than today.
}
To put it another way, can I use LINQ to XML to find the most recent date (MeetingDate
) for cong.Name
(PublicTalkCongregation
) that is prior to today. So that I can then update cong.LastInvited
to this date.
Make sense?
I am trying the proposed answer but getting exception:
Unhandled Exception: System.ArgumentNullException: Value cannot be null.
Parameter name: element
at System.Xml.Linq.XElement.op_Explicit(XElement element)
at ConsoleApp1.Program.<>c.<Main>b__2_0(XElement x) in D:\My Programs\2022\Backup MSA2\ConsoleApp1\ConsoleApp1\Program.cs:line 24
at System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext()
at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
at ConsoleApp1.Program.Main(String[] args) in D:\My Programs\2022\Backup MSA2\ConsoleApp1\ConsoleApp1\Program.cs:line 23
I should clarify that some of the older assignment history entries won't have the MeetingDate
\ PublicTalkCongregation
elements which case those history weeks should be bypassed.
Try following :
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Linq;
using System.Globalization;
namespace ConsoleApplication2
{
class Program
{
const string FILENAME = @"c:\temp\test.xml";
static void Main(string[] args)
{
XDocument doc = XDocument.Load(FILENAME);
XElement assignments = doc.Descendants("AssignmentHistory").FirstOrDefault();
List<Meeting> meetings = assignments.Elements().Select(x =>
new Meeting()
{
date = DateTime.ParseExact(x.Name.LocalName, "WyyyyMMdd", CultureInfo.InvariantCulture),
meetingDate = x.Descendants("MeetingDate").FirstOrDefault() == null ? new DateTime() : (DateTime)x.Descendants("MeetingDate").FirstOrDefault(),
congregation = (string)x.Descendants("PublicTalkCongregation").FirstOrDefault()
}).ToList();
}
}
}
public class Meeting
{
public DateTime date { get; set; }
public DateTime meetingDate { get; set; }
public string congregation { get; set; }
}