Вам нужно получить Foo разделы 2 и 3 с запросом вроде:
var foos = from xelem in root.Descendants("Foo")
where xelem.Attribute("id").Value == "2" || xelem.Attribute("id").Value == "3"
select xelem;
А затем повторите этот список и удалите их из родителей с помощью
xelem.Remove();
Затем просто добавьте их в правильный узел с помощью:
parentElem.Add(xelem);
В первом запросе вы получите оба раздела, затем удалите и добавите каждый в нужное место на дереве.
Вот полное решение:
var foos = (from xElem in xDoc.Root.Descendants("Foo")
where xElem.Attribute("id").Value == "2" || xElem.Attribute("id").Value == "3"
select xElem).ToList();
var newParentElem = (from xElem in xDoc.Root.Descendants("SubSection")
where xElem.Attribute("id").Value == "C"
select xElem).Single();
foreach(var xElem in foos)
{
xElem.Remove();
newParentElem.Add(xElem);
}
После этого ваш xDoc должен иметь правильное дерево.