我期待XML输出如下:
<MyBase type="MyDerived"
xmlns="http://www.mynamespace.com/MySchema" />
相反,我的实际输出如下:
<MyBase i:type="MyDerived"
xmlns="http://www.mynamespace.com/MySchema"
xmlns:i="http://www.w3.org/2001/XMLSchema-instance" />
我使用以下类定义来尝试生成我期望的输出:
MyBase.cs
namespace MyProject
{
[KnownType(typeof(MyDerived))]
[DataContract(Namespace = MyBase.Namespace)]
public abstract class MyBase
{
public const string Namespace = "http://www.mynamespace.com/MySchema";
}
}
MyDerived.cs
namespace MyProject.Events
{
[DataContract(Namespace = MyBase.Namespace)]
public sealed class MyDerived : MyBase {}
}
我正在使用以下序列化代码:
var knownTypes = new Type[]
{
typeof(MyDerived)
};
var xmlDictionary = new XmlDictionary(1);
var settings = new DataContractSerializerSettings();
settings.KnownTypes = knownTypes;
settings.RootNamespace = xmlDictionary.Add(MyBase.Namespace);
serializer = new DataContractSerializer(typeof(MyBase), settings);
var actual = String.Empty;
using (var memoryStream = new MemoryStream())
{
serializer.WriteObject(memoryStream, new MyDerived());
memoryStream.Position = 0;
using (var streamReader = new StreamReader(memoryStream))
{
actual = streamReader.ReadToEnd();
}
}
我不确定为什么它为我的派生对象使用XMLSchema-instance
命名空间而不是我指定使用的命名空间。我花了一个多小时在StackOverflow,谷歌和MSDN上挖掘,试图弄清楚我做错了什么,但我必须错过它。它看起来如此接近,一定是一个简单的错误。
这是我的类结构的问题,还是我以某种方式误用了属性?
如何获得预期的输出?
答案 0 :(得分:2)
您可能只是误读了XML并且事情正在按预期工作。在您的XML中,命名空间xmlns:i="http://www.w3.org/2001/XMLSchema-instance"
仅用于限定属性 i:type
,而不是其他任何内容。您的所有实际数据都在您指定的命名空间中。如果对象本身位于不同的命名空间中,您会看到如下内容:
i:type="i:MyDerived"
但你不是。
http://www.w3.org/2001/XMLSchema-instance
是一个W3C全局标准命名空间,其知识内置于DataContractSerializer
(以及许多其他XML序列化程序)。它包含4个内置属性,在standards document中定义如下:
nil
:如果元素的值为true
,则表示元素可能有效·没有内容。
schemaLocation
和noNamespaceSchemaLocation
:用于提供有关架构文档的物理位置的提示。
type
:实例中的元素信息项可以使用属性type
显式声明其类型。该属性的值为·QName·。
您看到的i:type
是这些标准的,全球公认的属性中的最后一个。它说:“这个元素有以下类型”。 DataContractSerializer
使用它来表示.Net类型信息的原因可能包括:
这是标准的。例如XmlSerializer
recognizes and supports the same attribute。
您的元素可能有自己的名为type
的数据属性。如果是这样,它将驻留在自己的命名空间中,不是 http://www.w3.org/2001/XMLSchema-instance
。对于架构信息而非内容,后者按惯例保留,从而避免名称冲突。
有关详情,请参阅Understanding Known Types和Data Contract Known Types。
答案 1 :(得分:1)
不幸的是,即使使用自定义XmlWriter
,您也无法实现它。 DataContractSerializer
不像XMLSerializer
那样有效。添加到xml中的信息是为了支持以下事实:
行 xmlns:xsi =“http://www.w3.org/2001/XMLSchema-instance”告诉XML解析器应该根据模式验证此文档。
此外,这些名称空间也被视为保留名称空间。因此,如果您尝试覆盖它们.Net运行时将抛出异常。
@dbc解释得非常好,包含命名空间是一个非常标准的过程的一部分,对你的xml无害。
如果你真的需要摆脱这个默认命名空间,那么你只需要使用字符串替换方法 hack 你的XML输出。但这可能会让你在脱盐时遇到问题。