让你的内部对象与根属于同一个命名空间怎么样?这样,省略xmlns
子孙的宣言。您可以使用[assembly: ContractNamespace]
属性来覆盖程序集中所有协定的命名空间。参考数据合约名称举个例子。
Edit:下面通过一些例子进行详细说明。
假设您正在手动构建 XML 文档,并且没有为任何元素指定命名空间。
XDocument xmlDocument = new XDocument(
new XElement("Book",
new XElement("Title", "Animal Farm"),
new XElement("Author", "George Orwell"),
new XElement("Publisher",
new XElement("Name", "Secker and Warburg"),
new XElement("Location", "London"),
new XElement("Founded", 1910))));
return xmlDocument.ToString();
正如预期的那样,生成的 XML 没有命名空间声明:
<Book>
<Title>Animal Farm</Title>
<Author>George Orwell</Author>
<Publisher>
<Name>Secker and Warburg</Name>
<Location>London</Location>
<Founded>1910</Founded>
</Publisher>
</Book>
但是,如果您仅为根元素指定命名空间,则所有子元素都必须使用以下命令显式恢复出该默认命名空间:xml=""
宣言。根据命名空间默认 rules:
默认命名空间声明的范围从它出现的开始标记的开头延伸到相应结束标记的末尾,不包括任何内部默认命名空间声明的范围。对于空标签,范围是标签本身。
因此,以下代码(为根元素指定了命名空间)...
XDocument xmlDocument = new XDocument(
new XElement("{http://example.com/library}Book",
new XElement("Title", "Animal Farm"),
new XElement("Author", "George Orwell"),
new XElement("Publisher",
new XElement("Name", "Secker and Warburg"),
new XElement("Location", "London"),
new XElement("Founded", 1910))));
return xmlDocument.ToString();
...将给出以下 XML:
<Book xmlns="http://example.com/library">
<Title xmlns="">Animal Farm</Title>
<Author xmlns="">George Orwell</Author>
<Publisher xmlns="">
<Name>Secker and Warburg</Name>
<Location>London</Location>
<Founded>1910</Founded>
</Publisher>
</Book>
请注意孩子们如何<Publisher>
元素不需要恢复出根的命名空间,因为它们从父元素继承了“无命名空间”声明。
为了消除xmlns=""
声明中,为了演示,我们可以为所有后代分配相同的名称空间:
XDocument xmlDocument = new XDocument(
new XElement("{http://example.com/library}Book",
new XElement("{http://example.com/library}Title", "Animal Farm"),
new XElement("{http://example.com/library}Author", "George Orwell"),
new XElement("{http://example.com/library}Publisher",
new XElement("{http://example.com/library}Name", "Secker and Warburg"),
new XElement("{http://example.com/library}Location", "London"),
new XElement("{http://example.com/library}Founded", 1910))));
return xmlDocument.ToString();
这将给出一个 XML 文档,其命名空间仅在根中声明(并在所有后代中隐式继承):
<Book xmlns="http://example.com/library">
<Title>Animal Farm</Title>
<Author>George Orwell</Author>
<Publisher>
<Name>Secker and Warburg</Name>
<Location>London</Location>
<Founded>1910</Founded>
</Publisher>
</Book>
为了模拟涉及 Web 服务的场景,我们可以创建以下 WCF 服务。
[DataContract]
public class Book
{
[DataMember]
public string Title { get; set; }
[DataMember]
public string Author { get; set; }
[DataMember]
public Publisher Publisher { get; set; }
}
[DataContract]
public class Publisher
{
[DataMember]
public string Name { get; set; }
[DataMember]
public string Location { get; set; }
[DataMember]
public short Founded { get; set; }
}
[ServiceContract]
public interface ILibraryService
{
[OperationContract]
Book GetBook();
}
public class LibraryService : ILibraryService
{
public Book GetBook()
{
return new Book
{
Title = "Animal Farm",
Author = "George Orwell",
Publisher = new Publisher
{
Name = "Secker and Warburg",
Location = "London",
Founded = 1910,
}
};
}
}
我们在客户端应用程序中添加对上述服务的服务引用,使用其操作,并序列化结果,同时将其包含在根中Books
具有显式命名空间的元素:
using (var libraryClient = new LibraryServiceReference.LibraryServiceClient())
{
var book = libraryClient.GetBook();
var stringBuilder = new StringBuilder();
using (XmlWriter xmlWriter = XmlWriter.Create(stringBuilder))
{
xmlWriter.WriteStartElement("Books", "http://example.com/library");
var serializer = new XmlSerializer(book.GetType());
serializer.Serialize(xmlWriter, book);
xmlWriter.WriteEndElement();
}
return stringBuilder.ToString();
}
在这种情况下,内部元素Book
包含一个xmlns=""
宣言。
<?xml version="1.0" encoding="utf-16"?>
<Books xmlns="http://example.com/library">
<Book xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns="">
<ExtensionData />
<Author>George Orwell</Author>
<Publisher>
<ExtensionData />
<Founded>1910</Founded>
<Location>London</Location>
<Name>Secker and Warburg</Name>
</Publisher>
<Title>Animal Farm</Title>
</Book>
</Books>
如上所述,这xmlns=""
可以通过设置来消除Book
元素的命名空间(及其后代的命名空间)与根的命名空间相对应。为了XmlSerializer
类中,所有元素的默认命名空间可以通过其构造函数的第二个参数指定。 (实际技术会根据您使用的序列化策略而有所不同。)
using (var libraryClient = new LibraryServiceReference.LibraryServiceClient())
{
var book = libraryClient.GetBook();
var stringBuilder = new StringBuilder();
using (XmlWriter xmlWriter = XmlWriter.Create(stringBuilder))
{
xmlWriter.WriteStartElement("Books", "http://example.com/library");
var serializer = new XmlSerializer(book.GetType(), "http://example.com/library");
serializer.Serialize(xmlWriter, book);
xmlWriter.WriteEndElement();
}
return stringBuilder.ToString();
}
这将给出预期的结果:
<?xml version="1.0" encoding="utf-16"?>
<Books xmlns="http://example.com/library">
<Book xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<ExtensionData />
<Author>George Orwell</Author>
<Publisher>
<ExtensionData />
<Founded>1910</Founded>
<Location>London</Location>
<Name>Secker and Warburg</Name>
</Publisher>
<Title>Animal Farm</Title>
</Book>
</Books>