This is fairly easy to do.
var doc = XDocument.Parse(raw);
XNamespace fromNs = "clr-namespace:NsOne;assembly=AsmOne";
XNamespace toNs = "clr-namespace:NsTwo;assembly=AsmTwo";
// redefines "gcs", but doesn't change what namespace the elements are in
doc.Root.SetAttributeValue(XNamespace.Xmlns + "gcs", toNs);
// this actually changes the namespaces of the elements from the old to the new
foreach (var element in doc.Root.Descendants()
.Where(x => x.Name.Namespace == fromNs))
element.Name = toNs + element.Name.LocalName;
Both portions are needed to result in XAML that's both correct and easily-readable, because the namespace of the elements is stored separately from the xmlns
declarations in an XDocument
. If you only change what "gcs" means, then it will write xmlns
statements to keep the elements in their old namespace. If you only change what namespace the elements are in, then it will include xmlns="clr-namespace:NsTwo;assembly=AsmTwo"
statements as necessary, and ignore gcs
(which will still reference the old NsOne
).