views:

330

answers:

3

I am rewriting an existing XmlDocument, which contains an element that has a new default namespace defined (see below, the assemblyBinding element)

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <runtime>
    <legacyCasPolicy enabled="true" />
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
    </assemblyBinding>
  </runtime>
</configuration>

I need to be able to add new nodes to this 'assemblyBinding' element, without them re-qualifying the namespace (because the .net runtime then considers the Xml invalid when treating the resulting file as an app.config file).

This is what I want:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <runtime>
    <legacyCasPolicy enabled="true" />
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">

      <dependentAssembly>
        <assemblyIdentity name="Dependency" publicKeyToken="9f10d5ba1865867c"/>
      </dependentAssembly>

    </assemblyBinding>
  </runtime>
</configuration>

... the 'dependentAssembly' element inherts the namespace of its parent.

After calling XmlDocument.CreateElement("dependentAssembly"); OR XmlDocument.CreateElement("dependentAssembly", "urn:schemas-microsoft-com:asm.v1"); OR XmlDocument.CreateElement("asm", "dependentAssembly", "urn:schemas-microsoft-com:asm.v1");

I keep getting something like this...

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <runtime>
    <legacyCasPolicy enabled="true" />
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">

      <asm:dependentAssembly xmlns:asm="urn:schemas-microsoft-com:asm.v1">
        <asm:assemblyIdentity name="Dependency" publicKeyToken="9f10d5ba1865867c"  xmlns:asm="urn:schemas-microsoft-com:asm.v1"/>
      </asm:dependentAssembly>

    </assemblyBinding>
  </runtime>
</configuration>

What do I need to do to get what I want?

A: 

If you're using .NET 3.5, you could use LINQ to XML. For example, this code:

XNamespace ns = "uri:ns";
XDocument doc = new XDocument
    (new XElement("root",
                  new XElement(ns + "child", new XAttribute("xmlns", ns),
                               new XElement(ns + "grandchild"))));
doc.Save("test.xml");

Results in this XML:

<?xml version="1.0" encoding="utf-8"?>
<root>
  <child xmlns="uri:ns">
    <grandchild />
  </child>
</root>

I tried getting the same result with XmlDocument, and so far I've failed...

Jon Skeet
A: 

The versions with and without the asm: prefix are the same. In both cases, the assemblyBinding, dependentAssembly, and assemblyIdentity elements are in the urn:schemas-microsoft-com:asm.v1 namespace.

John Saunders
A: 

I tried using AppendChildElement on a XPathNavigator in the document and it appears not to add multiple namespace declarations this way (the example does not add all the necessary elements but you get the idea):

        XmlDocument doc = new XmlDocument();
        doc.LoadXml(
            @"<?xml version='1.0' encoding='utf-8' ?>
                <configuration>
                  <runtime>
                    <legacyCasPolicy enabled='true' />
                    <assemblyBinding xmlns='urn:schemas-microsoft-com:asm.v1'>
                    </assemblyBinding>
                  </runtime>
                </configuration>
             ");       
        NameTable nt = new NameTable();
        XmlNamespaceManager nsm = new XmlNamespaceManager(nt);
        nsm.AddNamespace("x", "urn:schemas-microsoft-com:asm.v1");

        XPathNavigator node = doc.CreateNavigator().SelectSingleNode("//x:assemblyBinding", nsm);
        node.AppendChildElement("", "dependentAssembly", "urn:schemas-microsoft-com:asm.v1", "");

Fred

fredw
Actually, did you try XmlDocument.CreateElement("", "dependentAssembly", "urn:schemas-microsoft-com:asm.v1"); ie with empty prefix as in my example above?
fredw