I finally solved the namespace issue I was having, although I’ll probably burn for all eternity for the solution. In short, because of the behavior of XmlTextWriter, the only solution that could be implemented in a reasonable amount of time was to post-process the XML and strip out the extra namespace declarations.

So I started down the path of using XmlTextReader to spin through and collect up all the namespaces that I needed, then add those to the root node. After that I could use a regular expression to strip out all the unneeded ones. Turns out I had overlooked the fact that the input isn’t guaranteed to be well-formed XML. :-(

The “XML” is actually a template that our system uses to do some tag replacement. So the output of that process is well-formed, but the input can contain the “@” character inside element names. A no-no according to the XML spec.

So here it is, the all-regular-expression solution. I wouldn’t suggest you try this at home, but it does actually work, and seems to be quite fast (sub 1/4 second for a 1.5Mb input, and the typical input is more like 10K).

Note: this is made a little simpler because I know (since I just wrote out the “XML”) that all the namespace prefixes we care about start with ns, e.g. ns0, ns1, etc.

#region begin hairy namespace rectifying code here

//this is necessary because the XmlTextWriter puts in more namespace

//declarations than we want, which causes file bloat.

Regex strip = new Regex(@"xmlns\:ns\d=""[^""]*""");

ArrayList names = new ArrayList();

MatchCollection matches = strip.Matches(result);

foreach(Match match in matches)

{

string val = match.Value;

if(!val.StartsWith("xmlns:ns0"))

if(!names.Contains(match.Value))

names.Add(match.Value);

}

string fixedNamespaces = null;

StringBuilder sb = new StringBuilder();

foreach(string name in names)

{

sb.AppendFormat(" {0}",name);

}

fixedNamespaces = result;

int pos = fixedNamespaces.IndexOf(">",0);//should be the end of the xml declaration

pos = fixedNamespaces.IndexOf(">",pos+1);//should be end of root node.

fixedNamespaces = fixedNamespaces.Insert(pos,sb.ToString());

pos = fixedNamespaces.IndexOf(">",0);//should be the end of the xml declaration

pos = fixedNamespaces.IndexOf(">",pos+1);//should be end of root node.