我得到的是这:
- <?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>