To improve Mike's useful answer slightly.
The reason you can't just iterate Descendants
once is because AddAfterSelf()
creates copies. After the first removal you're iterating children of the removed element rather than their replacements in the document.
However, if you iterate them backwards, then any copied children will have already been processed, so you can get away with a single pass:
foreach(var x in xdoc.Descendants("x").Reverse())
{
x.AddAfterSelf(x.Nodes());
x.Remove();
}