I tried some of the solutions, but as stated by so many, there are some edge cases.
Used some of the regexes above, but came to the conclusion that a one step regex is not feasable.
So here is my solution, 2 step regex, find tags, within tags remove, do not alter cdata:
Func<Match, String> NamespaceRemover = delegate (Match match)
{
var result = match.Value;
if (String.IsNullOrEmpty(match.Groups["cdata"].Value))
{
// find all prefixes within start-, end tag and attributes and also namespace declarations
return Regex.Replace(result, "((?<=<|<\\/| ))\\w+:| xmlns(:\\w+)?=\".*?\"", "");
}
else
{
// cdata as is
return result;
}
};
// XmlDocument doc;
// string file;
doc.LoadXml(
Regex.Replace(File.ReadAllText(file),
// find all begin, cdata and end tags (do not change order)
@"<(?:\w+:?\w+.*?|(?<cdata>!\[CDATA\[.*?\]\])|\/\w+:?\w+)>",
new MatchEvaluator(NamespaceRemover)
)
);
For now it is 100% working for me.