C# – XmlDocument Prefix Not Being Outputted

cxmldocument

I am trying to add a prefix onto a few xmlnodes within a new XMLDocument (Created 100% from scratch, not loaded from a file etc).

In the simplest terms I have this :

XmlDocument doc = new XmlDocument();
XmlElement RootElement = (XmlElement)doc.AppendChild(doc.CreateElement("root"));
foreach (string line in CSV)
{
    XmlElement navPointElement = (XmlElement) RootElement.AppendChild(doc.CreateElement("navPoint"));
    XmlElement navPointTypeElement =(XmlElement) navPointElement.AppendChild(doc.CreateElement("type"));
    navPointTypeElement.Prefix = "acp";
    navPointTypeElement.InnerText = nodeCount == 0 ? "cover" : "article";
}

There is much more code but this gives you an idea of what I'm doing. Now the document outputs fine, but it completely skips over the prefix declarations. I have read around about defining namespaces, and I tried to the following to no avail.

XmlNamespaceManager ns = new XmlNamespaceManager(doc.NameTable);
ns.AddNamespace("acp", "http://www.namespace.com");

I'm sure it's something simple, but I can't quite find any documentation on it. The MSDN documentation for xmldocument prefix simply just adds the prefix much the same as I have done without the need for namespaces (Or atleast that's how they show it in their code samples).

Any help is much appreciated 🙂

Best Answer

Well, you do need a namespace. Something like <acp:type/> is invalid by itself because acp doesn't map to any namespace, which is what a prefix should do.

What you need to do is to set the namespace on the element you want to add on the call of CreateElement for the type element.

public class StackOverflow_10807173
{
    public static void Test()
    {
        XmlDocument doc = new XmlDocument();
        XmlElement RootElement = (XmlElement)doc.AppendChild(
            doc.CreateElement("root"));
        string[] CSV = "hello world how are you".Split(' ');
        int nodeCount = 0;
        XmlAttribute xmlnsAttr = doc.CreateAttribute(
            "xmlns", "acp", "http://www.w3.org/2000/xmlns/");
        string acpNamespace = "http://www.namespace.com";
        xmlnsAttr.Value = acpNamespace;
        RootElement.Attributes.Append(xmlnsAttr);
        foreach (string line in CSV)
        {
            XmlElement navPointElement = (XmlElement)RootElement.AppendChild(
                doc.CreateElement("navPoint"));
            XmlElement navPointTypeElement = (XmlElement)navPointElement.AppendChild(
                doc.CreateElement("type", acpNamespace)); // namespace here
            navPointTypeElement.Prefix = "acp";
            navPointTypeElement.InnerText = nodeCount == 0 ? "cover" : "article";
        }

        Console.WriteLine(doc.OuterXml);
    }
}

One note: you don't really need to add the namespace in the root element; it's just that if you don't do that, you'll have the xmlns:acp="yournamespace" attribute in all of the type elements (since that prefix isn't in scope). Adding that in a parent element makes adding it in the children elements unecessary.