XNamespace as additional attribute, why

443 views Asked by At

I want to achieve this:

    <?xml version="1.0" encoding="utf-8"?>
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
  <appSettings>    
    <add key="WriteToLogFile" value="true" xdt:Transform="SetAttributes(value)" xdt:Locator="Match(name)" />
    <add key="SendErrorEmail" value="false" xdt:Transform="SetAttributes(value)" xdt:Locator="Match(name)" />    
  </appSettings>
</configuration>

Here is my c# code:

var items = GetItems();
XNamespace xdtNamespace = "xdt";

XDocument doc = new XDocument(new XElement("configuration", new XAttribute(XNamespace.Xmlns + "xdt", "http://schemas.microsoft.com/XML-Document-Transform"),
new XElement("appSettings", from item in items
    select new XElement("add",
        new XAttribute("key", item.Key),
        new XAttribute("value", item.Value),
        new XAttribute(xdtNamespace + "Transform", "SetAttributes(value)"),
        new XAttribute(xdtNamespace + "Locator", "Match(name)")))));

doc.Declaration = new XDeclaration("1.0", "utf-8", null);                
doc.Save("Test.xml");

Output for my c# code is:

 <?xml version="1.0" encoding="utf-8"?>
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
  <appSettings>   
    <add key="WriteToLogFile" value="true" p4:Transform="SetAttributes(value)" p4:Locator="Match(name)" xmlns:p4="xdt" />
    <add key="SendErrorEmail" value="false" p4:Transform="SetAttributes(value)" p4:Locator="Match(name)" xmlns:p4="xdt" />    
  </appSettings>
</configuration>

As you can see, for each element there is an extra attribute xmlns:p4="xdt". And attributes Transform and Locator are prefixed with p4 instead of xdt. Why is it this happening?

I already read msdn documentation related to xml namespaces (and few other similar articles), but frankly speaking it is quite confusing, I didn't find anything helpful.

Are there any good articles, which explain in a nutshell my case?

1

There are 1 answers

0
Jon Skeet On BEST ANSWER

You're confusing a namespace alias (which you want to be xdt) with the namespace URI. You want to put the elements in the right namespace (by URI) but specify an xmlns attribute in the root element with the alias you want:

using System;
using System.Xml.Linq;

class Test
{
    static void Main(string[] args)
    {
        XNamespace xdt = "http://schemas.microsoft.com/XML-Document-Transform";

        XDocument doc = new XDocument(
            new XElement("configuration",
                new XAttribute(XNamespace.Xmlns + "xdt", xdt.NamespaceName),
                new XElement("appSettings",
                    new XElement("add",
                        new XAttribute("key", "WriteToLogFile"),
                        new XAttribute("value", true),
                        new XAttribute(xdt + "Transform", "SetAttributes(value)"),
                        new XAttribute(xdt + "Locator", "Match(name)")
                    )
                )
            )
        );
        Console.WriteLine(doc);
    }    
}

Output:

<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
  <appSettings>
    <add key="WriteToLogFile" value="true" xdt:Transform="SetAttributes(value)" xdt:Locator="Match(name)" />
  </appSettings>
</configuration>