Attributes and Elements are getting prefixed instead of using the default namespace

Last post 05-08-2008 11:01 PM by Samu Zhang - MSFT. 1 replies.

Sort Posts:

  • Attributes and Elements are getting prefixed instead of using the default namespace

    05-07-2008, 10:19 AM
    • Loading...
    • badgriffin
    • Joined on 05-07-2008, 1:49 PM
    • Posts 1

    I need to emit some XML using an XmlTextWriter that mostly uses the default namespace but in a couple of places needs to use an alternate namespace. A simplified version of the XML I need to emit is shown below:

    <?xml version="1.0" encoding="utf-8"?>
    <
    Foo
        attribute="value"
        extra:otherAttribute="value"
        xmlns:extra=http://foo/extra/
        xmlns=http://foo/default/>
      <
    Bar />
    </
    Foo>

    But what is happening is that the default namespace is getting emitted a second time as a prefixed namespace and the attributes and elements are getting assigned this prefix instead of being emitted without a prefix and using the default namespace.

    <?xml version="1.0" encoding="utf-8"?>
    <
    Foo xmlns:extra="http://foo/extra/"
        localName-value-only="value"                                       Emitted correctly using WriteAttributeString(localName, value)
        extra:localName-nsExtra-value="value"                          Emitted correctly using WriteAttributeString(localName, ns, value)
        p2:localName-nsDefault-value="value"                          Emitted incorrectly using WriteAttributeString(localName, ns, value)
        p2:prefixEmpty-localName-nsDefault-value="value"      Emitted incorrectly using WriteAttributeString(prefix (string.Empty), localName, ns, value)
        p2:prefixNull-localName-nsDefault-value="value"          Emitted incorrectly using WriteAttributeString(prefix (null), localName, ns, value)
        xmlns:p2="http://foo/default/"                                         Automagically added by XmlWriter. Why?
        xmlns="http://foo/default/">
      <
    p2:Bar />
    </
    Foo>

    My code looks like this:

    XmlWriterSettings outputSettings = new XmlWriterSettings();
    outputSettings.Encoding =
    Encoding.UTF8;
    outputSettings.NewLineOnAttributes =
    true;
    outputSettings.Indent =
    true;
    outputSettings.IndentChars = (
    "\t");

    string
    defaultNamespace = http://foo/default/;
    string extraNamespace = http://foo/extra/;

    XmlWriter
    output = XmlWriter.Create(@"c:\temp\foo.xml", outputSettings);

    output.WriteStartElement(
    "Foo", defaultNamespace);
    output.WriteAttributeString(
    "xmlns", "extra", null, extraNamespace);

    // As expected, this attribute is emitted without a namespace prefix and is, by definition,
    // in the namespace defaultNamespace.
    output.WriteAttributeString("localName-value-only", "value");

    // As expected, the XmlWriter already knows that extraNamespace has been mapped to "extra" so this
    // attribute is emitted with a prefix of "extra:".
    output.WriteAttributeString("localName-nsExtra-value", extraNamespace, "value");

    // At this point, the XmlWriter knows that the default namespace is defaultNamespace and that
    // the extraNamespace uses the prefix "extra:". We've already proven that when we emit an attribute
    // using the extraNamespace that the XmlWriter uses the correct prefix of "extra:". So, why do each
    // of the following lines of code cause the XmlWriter to unexpected ignore the default namespace and
    // create a new prefix p2 with the same EXACT namespace as the default namespace and then use the
    // "p2:" prefix on each of these attributes. They should be emitted without any namespace prefix
    // because they are all in the default namespace. If you comment out two of these and leave only
    // one of them you still get the same "p2:" prefixed results. I was hoping that one of the variations
    // would get the intended results but they all seem to produce the same results.

    output.WriteAttributeString("localName-nsDefault-value", defaultNamespace, "value");
    output.WriteAttributeString(
    "", "prefixEmpty-localName-nsDefault-value", defaultNamespace, "value");
    output.WriteAttributeString(
    null, "prefixNull-localName-nsDefault-value", defaultNamespace, "value");
     
    // Again, the XmlWriter uses the "p2:" prefix on this element even though it is clearly in the default
    // namespace and doesn't need a prefix.
    output.WriteStartElement("Bar", defaultNamespace);
    output.WriteEndElement();
    // Bar

    output.WriteEndElement();
    // Foo
     
    output.Flush();
    output.Close();

    Your first reaction is probably "well, if WriteAttributeString(localName, value) works the way you want it to, why don't you just use that?". The answer is that in our real application, deeper in this XML output, we need to redefine the default namespace to be something else. That part will fail with the error "The prefix '' cannot be redefined from '' to 'http://bar' within the same start element tag". The only way I have found to prevent this error is to explicitly add namespaces to the elements and attributes outside that inner block of XML. As soon as I do that, I'm getting these unecessary extra namespace definitions and prefixes that exactly match the default namespace.

    Any ideas?

     

  • Re: Attributes and Elements are getting prefixed instead of using the default namespace

    05-08-2008, 11:01 PM
    Answer

    Hi badgriffin ,

    Change your code to :

     

            XmlWriterSettings outputSettings = new XmlWriterSettings();
            outputSettings.Encoding = Encoding.UTF8;
            outputSettings.NewLineOnAttributes = true;
            outputSettings.Indent = true;
            outputSettings.IndentChars = ("\t");
    
            string defaultNamespace = "http://foo/default/";
            string extraNamespace = "http://foo/extra/";
    
            XmlWriter output = XmlWriter.Create(Server.MapPath("foo.xml"), outputSettings);
    
            output.WriteStartElement("Foo", defaultNamespace);
            output.WriteAttributeString("xmlns", "extra", null, extraNamespace);
    
            // As expected, this attribute is emitted without a namespace prefix and is, by definition,
            // in the namespace defaultNamespace.
            output.WriteAttributeString("localName-value-only", "value");
    
            // As expected, the XmlWriter already knows that extraNamespace has been mapped to "extra" so this
            // attribute is emitted with a prefix of "extra:".
            output.WriteAttributeString("localName-nsExtra-value", extraNamespace, "value");
    
            // At this point, the XmlWriter knows that the default namespace is defaultNamespace and that
            // the extraNamespace uses the prefix "extra:". We've already proven that when we emit an attribute
            // using the extraNamespace that the XmlWriter uses the correct prefix of "extra:". So, why do each
            // of the following lines of code cause the XmlWriter to unexpected ignore the default namespace and
            // create a new prefix p2 with the same EXACT namespace as the default namespace and then use the
            // "p2:" prefix on each of these attributes. They should be emitted without any namespace prefix
            // because they are all in the default namespace. If you comment out two of these and leave only
            // one of them you still get the same "p2:" prefixed results. I was hoping that one of the variations
            // would get the intended results but they all seem to produce the same results.
            output.WriteAttributeString("localName-nsDefault-value", null, "value");
            output.WriteAttributeString("", "prefixEmpty-localName-nsDefault-value", null, "value");
            output.WriteAttributeString(null, "prefixNull-localName-nsDefault-value", null, "value");
             
            // Again, the XmlWriter uses the "p2:" prefix on this element even though it is clearly in the default
            // namespace and doesn't need a prefix.
            output.WriteStartElement("Bar", defaultNamespace);
            output.WriteEndElement(); // Bar
    
            output.WriteEndElement(); // Foo
             
            output.Flush();
            output.Close();
     
    Sincerely,
    Samu Zhang
    Microsoft Online Community Support

    Please remember to click “Mark as Answer” on the post that helps you, and to click “Unmark as Answer” if a marked post does not actually answer your question. This can be beneficial to other community members reading the thread.
Page 1 of 1 (2 items)