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 current position is set at an attribute, the attribute and all remaining attributes in the element are returned. If the position is set at an XmlDeclaration NodeType, then all of the attributes of the declaration are written out. All other NodeTypes have no operation. 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()
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 takes 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 WriteAttributeString.
WriteStartAttribute
The WriteStartAttribute generates the start of an attribute and additionally takes a namespace prefix or a namespace Uniform Resource Identifier (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 have 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")
' Look up 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()
// 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");
// Look up 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 World Wide Web Consortium (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()
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()
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"/>