Search code examples
c#xmllinqlinq-to-xmlxelement

c# LINQ-to-XML update (save) list of elements in file after ordering


I have an XML file as such:

<?xml version="1.0" encoding="utf-8"?>
<FooMgr>
    <BlargDate>2017-03-06 10:26:21</BlargDate>
    <Bars>
        <Bar>
            <BarId>222</BarId>
            <BarVal>QWERTY</BarVal>
        </Bar>
        <Bar>
            <BarId>77</BarId>
            <BarVal>DVORAK</BarVal>
        </Bar>
        <Bar>
            <BarId>9999</BarId>
            <BarVal>AZERTY</BarVal>
        </Bar>
    </Bars>
</FooMgr>

and I am:

  • reading it in
  • adding a 'Bar' element
  • ordering it descending by BarId
  • attempting to save the updated/sorted xml back to the file.

although the added element is in the list after I save it, it does not keep the order I defined in code when saving. Here's what i go so far (mostly working valid code)

//read in the xml file
XDocument doc = XDocument.Load(...);

//add a new 'Bar' element
XElement bar1 = new XElement("Bar",
                      new XElement("BarId", 101),
                      new XElement("BarVal", "HCESAR"));
doc.Element("FooMgr").Element("Bars").Add(bar1);

//sort descending by BarId
IEnumerable<XElement> allBars = doc.Descendants("FooMgr")
                                   .Select(x => x.Element("Bars"))
                                   .Descendants("Bar")
                                   .ToArray();
allBars = allBars.OrderByDescending(s => int.Parse(s.Element("BarId").Value));

//save file
doc.Save(...);

// note: at this point the file successfully saves (along with the 
// new 'bar' value, but the order that is set for allBars does not 
// make it back into the file.

although this line:

allBars = allBars.OrderByDescending(s => int.Parse(s.Element("BarId").Value));

does seem to properly sort the 'Bars' elements in code, when I save it back to the file the order is not persisted.

Any thoughts?


Solution

  • You can do this before you call Save method:

    //Remove bar elements from your doc
    doc.Element("FooMgr").Element("Bars").Elements("Bar").Remove();
    //Add the ordered bar nodes
    doc.Element("FooMgr").Element("Bars").Add(allBars);
    
    //save file
    doc.Save(...);
    

    More info about Remove extension method and Add method