質問

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?

役に立ちましたか?

解決

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";
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top