我得到的是这:
<?xml ...> <rootelement xmlns:xsi="..." xmlns:xsd="..."> </rootelement>
并且我想删除两个xmlns声明。
重复:How to serialize an object to XML without getting xmlns=”…”?
阅读Microsoft的文档和几个解决方案在线,我已经发现了这个问题的解决方案。它与内置的XmlSerializer和自定义XML序列化通过IXmlSerialiazble工作。
为了白,我将使用迄今为止在此问题的答案中使用的相同的MyTypeWithNamespaces XML示例。
[XmlRoot("MyTypeWithNamespaces",Namespace="urn:Abracadabra",IsNullable=false)] public class MyTypeWithNamespaces { // As noted below,per Microsoft's documentation,if the class exposes a public // member of type XmlSerializerNamespaces decorated with the // XmlNamespacesDeclarationAttribute,then the XmlSerializer will utilize those // namespaces during serialization. public MyTypeWithNamespaces( ) { this._namespaces = new XmlSerializerNamespaces(new XmlQualifiedName[] { // Don't do this!! Microsoft's documentation explicitly says it's not supported. // It doesn't throw any exceptions,but in my testing,it didn't always work. // new XmlQualifiedName(string.Empty,string.Empty),// And don't do this: // new XmlQualifiedName("","") // DO THIS: new XmlQualifiedName(string.Empty,"urn:Abracadabra") // Default Namespace // Add any other namespaces,with prefixes,here. }); } // If you have other constructors,make sure to call the default constructor. public MyTypeWithNamespaces(string label,int epoch) : this( ) { this._label = label; this._epoch = epoch; } // An element with a declared namespace different than the namespace // of the enclosing type. [XmlElement(Namespace="urn:Whoohoo")] public string Label { get { return this._label; } set { this._label = value; } } private string _label; // An element whose tag will be the same name as the property name. // Also,this element will inherit the namespace of the enclosing type. public int Epoch { get { return this._epoch; } set { this._epoch = value; } } private int _epoch; // Per Microsoft's documentation,you can add some public member that // returns a XmlSerializerNamespaces object. They use a public field,// but that's sloppy. So I'll use a private backed-field with a public // getter property. Also,per the documentation,for this to work with // the XmlSerializer,decorate it with the XmlNamespaceDeclarations // attribute. [XmlNamespaceDeclarations] public XmlSerializerNamespaces Namespaces { get { return this._namespaces; } } private XmlSerializerNamespaces _namespaces; }
这就是这个类。现在,有人反对在他们的类中有一个XmlSerializerNamespaces对象;但是你可以看到,我整洁地把它放在默认构造函数中,并暴露了一个公共属性来返回命名空间。
现在,当需要序列化类时,您将使用以下代码:
MyTypeWithNamespaces myType = new MyTypeWithNamespaces("myLabel",42); /****** OK,I just figured I could do this to make the code shorter,so I commented out the below and replaced it with what follows: // You have to use this constructor in order for the root element to have the right namespaces. // If you need to do custom serialization of inner objects,you can use a shortened constructor. XmlSerializer xs = new XmlSerializer(typeof(MyTypeWithNamespaces),new XmlAttributeOverrides(),new Type[]{},new XmlRootAttribute("MyTypeWithNamespaces"),"urn:Abracadabra"); ******/ XmlSerializer xs = new XmlSerializer(typeof(MyTypeWithNamespaces),new XmlRootAttribute("MyTypeWithNamespaces") { Namespace="urn:Abracadabra" }); // I'll use a MemoryStream as my backing store. MemoryStream ms = new MemoryStream(); // This is extra! If you want to change the settings for the XmlSerializer,you have to create // a separate XmlWriterSettings object and use the XmlTextWriter.Create(...) factory method. // So,in this case,I want to omit the XML declaration. XmlWriterSettings xws = new XmlWriterSettings(); xws.OmitXmlDeclaration = true; xws.Encoding = Encoding.UTF8; // This is probably the default // You could use the XmlWriterSetting to set indenting and new line options,but the // XmlTextWriter class has a much easier method to accomplish that. // The factory method returns a XmlWriter,not a XmlTextWriter,so cast it. XmlTextWriter xtw = (XmlTextWriter)XmlTextWriter.Create(ms,xws); // Then we can set our indenting options (this is,of course,optional). xtw.Formatting = Formatting.Indented; // Now serialize our object. xs.Serialize(xtw,myType,myType.Namespaces);
一旦你这样做,你应该得到以下输出:
<MyTypeWithNamespaces> <Label xmlns="urn:Whoohoo">myLabel</Label> <Epoch>42</Epoch> </MyTypeWithNamespaces>
我已经成功地在最近的一个项目中使用这种方法,一个深入层次的类被序列化为XML的Web服务调用。微软的文档不太清楚在公开访问的XmlSerializerNamespaces成员一旦你创建它,怎么办,很多人认为它是无用的。但是通过遵循它们的文档并以上面所示的方式使用它们,您可以定制XmlSerializer如何为您的类生成XML,而不使用不支持的行为或通过实现IXmlSerializable“滚动自己的”序列化。
我希望这个答案将永远搁置,如何摆脱XmlSerializer生成的标准xsi和xsd命名空间。
更新:我只是想确保我回答OP的问题,删除所有命名空间。我的代码上面将工作为此;让我告诉你怎么样。现在,在上面的例子中,你真的不能摆脱所有命名空间(因为有两个命名空间在使用)。在你的XML文档中的某个地方,你将需要一些类似于xmlns =“urn:Abracadabra”xmlns:w =“urn:Whoohoo。如果示例中的类是更大的文档的一部分,必须为Abracadbra和Whoohoo中的任何一个(或两者)声明。如果不是,那么一个或两个命名空间中的元素必须用某种类型的前缀来装饰(你不能有两个默认命名空间,对吗?因此,对于这个例子,Abracadabra是默认的命名空间,我可以在MyTypeWithNamespaces类中为Whoohoo命名空间添加命名空间前缀,如下所示:
public MyTypeWithNamespaces { this._namespaces = new XmlSerializerNamespaces(new XmlQualifiedName[] { new XmlQualifiedName(string.Empty,"urn:Abracadabra"),// Default Namespace new XmlQualifiedName("w","urn:Whoohoo") }); }
现在,在我的类定义中,我指出< Label />元素在命名空间“urn:Whoohoo”中,因此我不需要进一步做任何事。当我现在序列化类使用我上面的序列化代码不变,这是输出:
<MyTypeWithNamespaces xmlns:w="urn:Whoohoo"> <w:Label>myLabel</w:Label> <Epoch>42</Epoch> </MyTypeWithNamespaces>
因为< Label>在与文档的其余部分不同的命名空间中,它在某种程度上必须用命名空间“装饰”。请注意,仍然没有xsi和xsd命名空间。
这结束了我对另一个问题的回答。但我想确保我回答OP的问题,使用没有命名空间,因为我觉得我还没有真正解决它。假设< Label>是与文档的其余部分相同的命名空间的一部分,在这种情况下urn:Abracadabra:
<MyTypeWithNamespaces> <Label>myLabel<Label> <Epoch>42</Epoch> </MyTypeWithNamespaces>
你的构造函数看起来像在我的第一个代码示例,以及检索默认命名空间的public属性:
// As noted below,if the class exposes a public // member of type XmlSerializerNamespaces decorated with the // XmlNamespacesDeclarationAttribute,then the XmlSerializer will utilize those // namespaces during serialization. public MyTypeWithNamespaces( ) { this._namespaces = new XmlSerializerNamespaces(new XmlQualifiedName[] { new XmlQualifiedName(string.Empty,"urn:Abracadabra") // Default Namespace }); } [XmlNamespaceDeclarations] public XmlSerializerNamespaces Namespaces { get { return this._namespaces; } } private XmlSerializerNamespaces _namespaces;
然后,稍后,在使用MyTypeWithNamespaces对象将其序列化的代码中,您将调用它,如上所述:
MyTypeWithNamespaces myType = new MyTypeWithNamespaces("myLabel",42); XmlSerializer xs = new XmlSerializer(typeof(MyTypeWithNamespaces),new XmlRootAttribute("MyTypeWithNamespaces") { Namespace="urn:Abracadabra" }); ... // Above,you'd setup your XmlTextWriter. // Now serialize our object. xs.Serialize(xtw,myType.Namespaces);
并且XmlSerializer会吐出与上面刚刚显示的相同的XML,在输出中没有额外的命名空间:
<MyTypeWithNamespaces> <Label>myLabel<Label> <Epoch>42</Epoch> </MyTypeWithNamespaces>