Search code examples
c#linq-to-xml

Trying to add new elements into XML using XML to LINQ in the right sort order


I am trying to add some entries to a XML file:

foreach(var talkNumber in listNumbers)
{
       var newElem = new XElement("PublicTalk",
                               new XAttribute("Number", talkNumber),
                               new XAttribute("Excluded", false),
                               new XAttribute("ExcludedFromDate", "1900-01-01"),
                               new XAttribute("Note", ""),
                               new XAttribute("TimesHeard", 0),
                               new XAttribute("LastHeard", "1900-01-01")
                              );
       ptLangInfo.Add(newElem);
}

XML

<?xml version="1.0" encoding="utf-8"?>
<PublicTalkTitles>
  <!-- English -->
  <eng>
    <PublicTalk Number="21" Excluded="false" ExcludedFromDate="1900-01-01" Note="" TimesHeard="1" LastHeard="2023-10-15" />
    <PublicTalk Number="1" Excluded="false" ExcludedFromDate="1900-01-01" Note="" TimesHeard="0" LastHeard="1900-01-01" />
    <PublicTalk Number="2" Excluded="false" ExcludedFromDate="1900-01-01" Note="" TimesHeard="0" LastHeard="1900-01-01" />
    <PublicTalk Number="3" Excluded="false" ExcludedFromDate="1900-01-01" Note="" TimesHeard="0" LastHeard="1900-01-01" />
  </eng>
</PublicTalkTitles>

The problem as you can see is that I want to add these new items in the correct numerical order to the existing ones. They get added to the bottom.

In my code snippet ptLangInfo is the eng element.


Solution

  • The method XContainer.Elements() returns an IEnumerable<XElement> not an IList<XElement>. As such there's no builtin log(n) way to insert an element into the enumeration of child elements using a binary search and assuming it's already sorted.

    Thus I'd recommend just sorting them afterwards:

    // Order the elements by the Number attribute
    var ordered = ptLangInfo.Elements("PublicTalk")
        .OrderBy(e => (int?)e.Attribute("Number"))
        .ToList();
    // Remove the elements from ptLangInfo using System.Xml.Linq.Extensions.Remove()
    ordered.Remove(); 
    // Add them back in the new order
    ptLangInfo.Add(ordered);
    

    Demo fiddle here.