Doing this with a text search and replacement should be done using StringBuilder
to avoid the normal issues of creating strings in a loop (lots of garbage). It also is very hard to prevent false positives (what if text matching the attribute occurs in a text node?)
Better options, with different tradeoffs include:
- Load into XDocument or XmlDocument, iterate through the tree replacing matching attributes.
- Use an XSLT
- Read from an XmlReader and write directly to an XmlWriter, with changed attributes.
Of these #3 avoids loading the whole document into memory. #2 requires XSLT skills but easily allows an arbitrary number of replacements (the core of the XSLT could be a template, with the new,old attribute pairs injected at runtime). #1 is likely to be simplest, but with the whole document in memory, and overhead of handling multiple replacements.
I would likely look at XSLT with Xml Reader/Writer approach as a backup.
However #1 should be simplest to implement, something like (ignoring XML namespaces amongst other details):
using System.Xml.Linq;
using System.Xml.XPath;
var xdoc = XDocument.Load(....);
var nav = xdoc.CreateNavigator();
foreach (repl in replacements) {
var found = (XPathNodeIterator) nav.Evaluate("//@" + repl.OldName);
while (found.MoveNext()) {
var node = found.Current;
var val = node.Value;
node.DeleteSelf(); // Moves ref to parent.
node.CreateAttribute("", repl.NewName, "", val);
}
}
The final choice will depend with balancing performance (especially memory if working with large documents) and complexity. but only you (and your team) can make that call.