Domanda

I am trying to generate XML via code (LINQ to XML) which follows a particular pattern with respect to namespace prefixes. I want to generate the following output consisting of 2 XML namespaces (an example illustrating the case; order of attributes irrelevant):

<name1 xmlns:space2="urn:schemas-upnp-org:namespace2/" xmlns="urn:schemas-upnp-org:namespace1/" name2="foo" space2:name4="demo">
  <name3>bar</name3>
</name1>

It is essential that namespace1 is the default namespace (no prefix) and namespace2 has a prefix of "space2" (I know, but don't blame me - there are standards which require such things).

I tried many different approaches in C#. The most likely I would assume would be the following:

public static readonly XNamespace NS1 = "urn:schemas-upnp-org:namespace1/";
public static readonly XNamespace NS2 = "urn:schemas-upnp-org:namespace2/";

public static readonly XName Name1 = NS1 + "name1";
public static readonly XName Name2 = NS1 + "name2";
public static readonly XName Name3 = NS1 + "name3";
public static readonly XName Name4 = NS2 + "name4"; // in namespace 2

void Test() {
    var y = new XElement(Name1,
            new XAttribute(XNamespace.Xmlns + "space2", NS2.NamespaceName),
            new XAttribute(Name2, "foo"),
            new XAttribute(Name4, "demo"),
            new XElement(Name3, "bar"));
    Trace.WriteLine(y.ToString());
}

For some reason however, this goes wrong. Some of the elements in namespace1 get assigned a weird prefix of "p1". Even though they use the same namespace reference, it seems that LINQ thinks the namespaces of Name1 and Name2 are different, and declares it twice:

<name1 xmlns:space2="urn:schemas-upnp-org:namespace2/" p1:name2="foo" space2:name4="demo" xmlns:p1="urn:schemas-upnp-org:namespace1/" xmlns="urn:schemas-upnp-org:namespace1/">
  <p1:name3>bar</p1:name3>
</name1>

The issue does not seem to arise if I assign a prefix to namespace1 or if I remove the attribute from namespace2, but that does not help since that would not help with the problem.

So the essence of the question is: Why does LINQ assign two different namespace declarations in the XML to NS1? How can it be configured to always be mapped to the default namespace?

È stato utile?

Soluzione

You are specifying namespace for attribute "foo" which creates second mapping for your default namespace. As result there are 2 valid mappings and either of them (likely latest) can be picked for nodes.

Note that attributes are in empty namespace unless they have explicit prefix - so your code actually generates different XML: your attribute name is {urn:schemas-upnp-org:namespace2/}foo instead of {}foo.

Fix: don't specify namespace for "foo"

  public static readonly XName Name2 = "name2";
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top