7

I want to use XmlWriter to write something like this (all in one namespace):

<Root xmlns="http://tempuri.org/nsA">
  <Child attr="val" />
</Root>

but the closest I can seem to get is this:

<p:Root xmlns:p="http://tempuri.org/nsA">
  <p:Child p:attr="val" />
</p:Root>

using this code:

using System;
using System.Text;
using System.Xml;

namespace ConsoleApplication1
{
    internal class Program
    {
        private const string ns = "http://tempuri.org/nsA";
        private const string pre = "p";

        private static void Main(string[] args)
        {
            var sb = new StringBuilder();
            var settings = new XmlWriterSettings
                     {
                       NamespaceHandling = NamespaceHandling.OmitDuplicates, 
                                             /* ineffective */             
                       Indent = true
                     };
            using (XmlWriter writer = XmlWriter.Create(sb, settings))
            {
                writer.WriteStartElement(pre, "Root", ns);
                writer.WriteStartElement(pre, "Child", ns);
                writer.WriteAttributeString(pre, "attr", ns, "val"); 
                                             // breaks namespaces    
                writer.WriteEndElement();
                writer.WriteEndElement();
            }
            Console.WriteLine(sb.ToString());
        }
    }
}

When I don't specify a prefix, I get:

<Root xmlns="http://tempuri.org/nsA">
  <Child p2:attr="val" xmlns:p2="http://tempuri.org/nsA" />
</Root>

The generation of these "phantom" prefixes in duplicate namespaces occurs throughout the generated document (p3, p4, p5 etc).

When I don't write attributes, I get the output I want (except it's missing the attributes, obviously).

Why isn't XmlWriter omitting duplicate namespaces like I asked?

SteveC
  • 15,808
  • 23
  • 102
  • 173
lesscode
  • 6,221
  • 30
  • 58

1 Answers1

4

Try like this:

using System;
using System.Text;
using System.Xml;

class Program
{
    private const string ns = "http://tempuri.org/nsA";

    static void Main()
    {
        var settings = new XmlWriterSettings
        {
            Indent = true
        };
        using (var writer = XmlWriter.Create(Console.Out, settings))
        {
            writer.WriteStartElement("Root", ns);
            writer.WriteStartElement("Child");
            writer.WriteAttributeString("attr", "", "val");
            writer.WriteEndElement();
            writer.WriteEndElement();
        }
    }
}
Darin Dimitrov
  • 1,023,142
  • 271
  • 3,287
  • 2,928
  • 1
    Thanks! That works, albeit totally counter-intuitive, since attributes have namespaces too. – lesscode Aug 09 '11 at 15:29
  • Or use Darin answer to the [SO](http://stackoverflow.com/questions/2500111/how-do-i-add-a-default-namespace-with-no-prefix-using-xmlserializer) question – SteveC Nov 22 '12 at 11:57
  • Anyone found a better solution? This ns management is suppose is supposed to be automatic! :( I especially love the last example on here: http://msdn.microsoft.com/en-us/library/d1a1csew%28v=vs.80%29.aspx – Fowl Apr 30 '13 at 01:06
  • It's good to know that creates the desired output, but is there any explanation for this behavior? Especially one based upon which one can calmly rely on the attributes seemingly written out without a namespace still have the intended namespace attached to them when read with an `XmlReader`? – O. R. Mapper Feb 26 '14 at 22:44