Attribute Namespace Prefixes in the XmlTextWriter

There are multiple ways of handling namespace prefixes for an attribute with the XmlTextWriter: WriteAttributes, WriteAttributeString, and WriteStartAttribute.

WriteAttributes

If the current position is an element node, the WriteAttributes method writes all the attributes found at the current position in the XmlReader. If the XmlReader has a namespace prefix declared, the WriteAttributes method writes the namespace prefix in addition to the attributes. The following code example shows how the WriteAttributes method writes the namespace prefix with the attribute.

Dim r As XmlTextReader = CreateTextReaderStr("<ROOT xmlns:p='n' p:a='abc'/>")
r.Read()
r.MoveToAttribute("p:a")

Dim tw As New XmlTextWriter(Console.Out)
tw.WriteStartElement("ROOT")
tw.WriteAttributes(r, False)
tw.WriteEndElement()
[C#]
XmlTextReader r = CreateTextReaderStr("<ROOT xmlns:p='n' p:a='abc'/>");
r.Read();
r.MoveToAttribute("p:a");

XmlTextWriter tw = new XmlTextWriter(Console.Out);
tw.WriteStartElement("ROOT");
tw.WriteAttributes(r, false);
tw.WriteEndElement();

Output

<ROOT p:a="abc" xmlns:p="n" />

WriteAttributeString

Another way of handling prefixes in a namespace is to have the application use one of the WriteAttributeString methods that take a namespace as a prefix. One of the WriteAttributeString methods takes in, as arguments, an attribute name, an attribute value, and a namespace, and writes out the attribute with the given value, and associates it with the namespace.

Another of the WriteAttributeString methods uses a user-defined namespace prefix, and associates the attribute with that prefix when writing the attribute. For sample code showing how to use the WriteAttributeString method and a user-defined namespace prefix, see XmlWriter.WriteAttributeString Method (String, String, String).

WriteStartAttribute

The WriteStartAttribute generates the start of an attribute, and additionally takes a namespace prefix or a namespace URI as a parameter depending on the method used.

The following code example has the first input argument as a string that takes the namespace prefix bk, which is found by calling the LookupPrefix method. After the prefix, local name, and namespace has been set using the WriteStartAttribute, the WriteString method gives a value to the attribute.

' Write an element (this one is the root).
writer.WriteStartElement("bookstore")
' Write the namespace declaration.
writer.WriteAttributeString("xmlns", "bk", Nothing, "urn:samples")
writer.WriteStartElement("book")
' Lookup the prefix and then write the ISBN attribute.
Dim prefix As String = writer.LookupPrefix("urn:samples")
writer.WriteStartAttribute(prefix, "ISBN", "urn:samples")
writer.WriteString("1-861003-78")
writer.WriteEndAttribute()
' Write the style element.
writer.WriteStartElement(prefix, "style", "urn:samples")
writer.WriteString("hardcover")
writer.WriteEndElement()
' Write the end tag for the book element.
writer.WriteEndElement()
'Write the close tag for the root element.
writer.WriteEndElement()
                
[C#]
// Write an element (this one is the root).
writer.WriteStartElement("bookstore");   
// Write the namespace declaration.
writer.WriteAttributeString("xmlns", "bk", null, "urn:samples");
writer.WriteStartElement("book");
// Lookup the prefix and then write the ISBN attribute.
string prefix = writer.LookupPrefix("urn:samples");
writer.WriteStartAttribute(prefix, "ISBN", "urn:samples");
writer.WriteString("1-861003-78");
writer.WriteEndAttribute();
// Write the style element.
writer.WriteStartElement(prefix, "style", "urn:samples");
writer.WriteString("hardcover");
writer.WriteEndElement();
// Write the end tag for the book element.
writer.WriteEndElement();
// Write the close tag for the root element.
writer.WriteEndElement();

Output

<bookstore xmlns:bk="urn:samples">
  <book bk:ISBN="1-861003-78">
      <bk:style>hardcover</bk:style>
  </book>
</bookstore>

If attributes have an associated namespace URI, then the attribute must also have a prefix, according to Namespace Defaulting in the W3C Namespaces in XML recommendation. The following code example shows that the prefix must be included when writing out an attribute with the WriteAttributeString method.

Dim w As New XmlTextWriter(Console.Out)
w.WriteStartElement("root")
w.WriteAttributeString("order", "urn:1", "123")
w.WriteEndElement()
w.Close()
[C#]
XmlTextWriter w = new XmlTextWriter(Console.Out);
w.WriteStartElement("root");
w.WriteAttributeString("order","urn:1", "123");
w.WriteEndElement();
w.Close();

Output

<root n1:order="123" xmlns:n1="urn:1"/>

This output occurs even if the root element is associated with the default namespace urn:1. The prefixes are named n{i} where i starts at 1. The index starts at 1 again for each element. Therefore, if a nested child element also needs a generated prefix it uses n1.

The following code example shows that attributes are written before namespace declarations, when writing multiple attributes with different namespaces.

Dim w As New XmlTextWriter(Console.Out)
w.WriteStartElement("root")
w.WriteAttributeString("order", "urn:1", "123")
w.WriteAttributeString("book", "urn:2", "The Great Escape")
w.WriteEndElement()
w.Close()
[C#]
XmlTextWriter w = new XmlTextWriter(Console.Out);
w.WriteStartElement("root");
w.WriteAttributeString("order","urn:1", "123");
w.WriteAttributeString("book","urn:2", "The Great Escape");
w.WriteEndElement();
w.Close();

Output

<root n1:order="123" n2:book="The Great Escape" xmlns:n1="urn:1" xmlns:n2="urn:2"/>

See Also

XmlTextWriter Class | XmlTextWriter Members | XmlWriter Class | XmlWriter Members