XElement default namespace on attributes provides

2019-07-04 06:22发布

I am having trouble creating an XML document that contains a default namespace and a named namespace, hard to explain easier to just show what I am trying to produce...

<Root xmlns="http://www.adventure-works.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:SchemaLocation="http://www.SomeLocatation.Com/MySchemaDoc.xsd">
  <Book title="Enders Game" author="Orson Scott Card" />
  <Book title="I Robot" author="Isaac Asimov" />
</Root>

but what I end up with is this...

<Root xmlns="http://www.adventure-works.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:SchemaLocation="http://www.SomeLocatation.Com/MySchemaDoc.xsd">
  <Book p3:title="Enders Game" p3:author="Orson Scott Card" xmlns:p3="http://www.adventure-works.com" />
  <Book p3:title="I Robot" p3:author="Isaac Asimov" xmlns:p3="http://www.adventure-works.com" />
</Root>

The code that I wrote to produce this XML snippet is this...

  XNamespace aw = "http://www.adventure-works.com";
  XNamespace xsi = "http://www.w3.org/2001/XMLSchema-instance";
  XElement root = new XElement(aw + "Root",
      new XAttribute("xmlns", "http://www.adventure-works.com"),
      new XAttribute(XNamespace.Xmlns + "xsi", "http://www.w3.org/2001/XMLSchema-instance"),
      new XAttribute(xsi + "SchemaLocation", "http://www.SomeLocatation.Com/MySchemaDoc.xsd"),

      new XElement(aw + "Book",
        new XAttribute(aw + "title", "Enders Game"),
        new XAttribute(aw + "author", "Orson Scott Card")),
      new XElement(aw + "Book",
        new XAttribute(aw + "title", "I Robot"),
        new XAttribute(aw + "author", "Isaac Asimov")));

based on an example on MSDN

****EDIT****

Ok, with some more experimentation I am now very confused on how XML namespaces work....

if I remove the aw + theattribute I get what I was after...but now it seems that what I was after is not actually what I expected. I thought that namespaces were inherited from their parents, is this not true of attributes as well? because, this code to read the attributes does not work as I expected...

  XElement xe = XElement.Parse(textBox1.Text);
  XNamespace aw = "http://www.adventure-works.com";
  var qry = from x in xe.Descendants(aw + "Book")
            select (string)x.Attribute(aw + "author");

However if I remove the aw + on the attribute its ok, leading me to assume that I cannot have attributes in the default namespace. Is this correct?

2条回答
仙女界的扛把子
2楼-- · 2019-07-04 07:03

Good question. I dug around a bit, and found this bit of the XML spec:

A default namespace declaration applies to all unprefixed element names within its scope. Default namespace declarations do not apply directly to attribute names; the interpretation of unprefixed attributes is determined by the element on which they appear.

It later goes on to give this example:

For example, each of the bad empty-element tags is illegal in the following:

<!-- http://www.w3.org is bound to n1 and n2 -->
<x xmlns:n1="http://www.w3.org" 
   xmlns:n2="http://www.w3.org" >
  <bad a="1"     a="2" />
  <bad n1:a="1"  n2:a="2" />
</x>

However, each of the following is legal, the second because the default namespace does not > apply to attribute names:

<!-- http://www.w3.org is bound to n1 and is the default -->
<x xmlns:n1="http://www.w3.org" 
   xmlns="http://www.w3.org" >
  <good a="1"     b="2" />
  <good a="1"     n1:a="2" />
</x>

So basically, it looks like attribute names don't get namespaces by default, which explains everything you've seen :)

查看更多
放我归山
3楼-- · 2019-07-04 07:18
XElement doc = XElement.Parse(ToXml());
doc.DescendantsAndSelf().Attributes().Where(a => a.IsNamespaceDeclaration).Remove();
var ele = doc.DescendantsAndSelf();
foreach (var el in ele)
    el.Name = ns != null ? ns + el.Name.LocalName : el.Name.LocalName;

For anyone else who spent 2 days trying to find an answer.

查看更多
登录 后发表回答