C# 在 .NET 中序列化对象时省略所有 xsi 和 xsd 命名空间?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/625927/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-04 10:47:19  来源:igfitidea点击:

Omitting all xsi and xsd namespaces when serializing an object in .NET?

c#.netxml-serialization

提问by NetSide

The code looks like this:

代码如下所示:

StringBuilder builder = new StringBuilder();
XmlWriterSettings settings = new XmlWriterSettings();
settings.OmitXmlDeclaration = true;
using (XmlWriter xmlWriter = XmlWriter.Create(builder, settings))
{
    XmlSerializer s = new XmlSerializer(objectToSerialize.GetType());
    s.Serialize(xmlWriter, objectToSerialize);
}

The resulting serialized document includes namespaces, like so:

生成的序列化文档包含命名空间,如下所示:

<message xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" 
    xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" 
    xmlns="urn:something">
 ...
</message>

To remove the xsi and xsd namespaces, I can follow the answer from How to serialize an object to XML without getting xmlns=”…”?.

要删除 xsi 和 xsd 命名空间,我可以按照How to serialize an object to XML without getting xmlns="..."? .

I want my message tag as <message>(without any namespace attributes). How can I do this?

我希望我的消息标记为<message>(没有任何命名空间属性)。我怎样才能做到这一点?

采纳答案by Thomas Levesque

...
XmlSerializer s = new XmlSerializer(objectToSerialize.GetType());
XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
ns.Add("","");
s.Serialize(xmlWriter, objectToSerialize, ns);

回答by Cheeso

This is the first of my two answers to the question.

这是我对这个问题的两个答案中的第一个。

If you want fine control over the namespaces - for example if you want to omit some of them but not others, or if you want to replace one namespace with another, you can do this using XmlAttributeOverrides.

如果您想对命名空间进行精细控制 - 例如,如果您想省略其中一些而不是其他命名空间,或者如果您想用另一个命名空间替换一个命名空间,您可以使用XmlAttributeOverrides来做到这一点。

Suppose you have this type definition:

假设你有这个类型定义:

// explicitly specify a namespace for this type,
// to be used during XML serialization.
[XmlRoot(Namespace="urn:Abracadabra")]
public class MyTypeWithNamespaces
{
    // private fields backing the properties
    private int _Epoch;
    private string _Label;

    // explicitly define a distinct namespace for this element
    [XmlElement(Namespace="urn:Whoohoo")]
    public string Label
    {
        set {  _Label= value; } 
        get { return _Label; } 
    }

    // this property will be implicitly serialized to XML using the
    // member name for the element name, and inheriting the namespace from
    // the type.
    public int Epoch
    {
        set {  _Epoch= value; } 
        get { return _Epoch; } 
    }
}

And this serialization pseudo-code:

这个序列化伪代码:

        var o2= new MyTypeWithNamespaces() { ..initializers...};
        ns.Add( "", "urn:Abracadabra" );
        XmlSerializer s2 = new XmlSerializer(typeof(MyTypeWithNamespaces));
        s2.Serialize(System.Console.Out, o2, ns);

You would get something like this XML:

你会得到这样的 XML:

<MyTypeWithNamespaces xmlns="urn:Abracadabra">
  <Label xmlns="urn:Whoohoo">Cimsswybclaeqjh</Label>
  <Epoch>97</Epoch>
</MyTypeWithNamespaces>

Notice that there is a default namespace on the root element, and there is also a distinct namespace on the "Label" element. These namespaces were dictated by the attributes decorating the type, in the code above.

请注意,根元素上有一个默认命名空间,“Label”元素上也有一个不同的命名空间。在上面的代码中,这些命名空间由修饰类型的属性决定。

The Xml Serialization framework in .NET includes the possibility to explicitly overridethe attributes that decorate the actual code. You do this with the XmlAttributesOverrides class and friends. Suppose I have the same type, and I serialize it this way:

.NET 中的 Xml 序列化框架包括显式覆盖修饰实际代码的属性的可能性。您可以使用 XmlAttributesOverrides 类和朋友来执行此操作。假设我有相同的类型,并以这种方式序列化它:

        // instantiate the container for all attribute overrides
        XmlAttributeOverrides xOver = new XmlAttributeOverrides();

        // define a set of XML attributes to apply to the root element
        XmlAttributes xAttrs1 = new XmlAttributes();

        // define an XmlRoot element (as if [XmlRoot] had decorated the type)
        // The namespace in the attribute override is the empty string. 
        XmlRootAttribute xRoot = new XmlRootAttribute() { Namespace = ""};

        // add that XmlRoot element to the container of attributes
        xAttrs1.XmlRoot= xRoot;

        // add that bunch of attributes to the container holding all overrides
        xOver.Add(typeof(MyTypeWithNamespaces), xAttrs1);

        // create another set of XML Attributes
        XmlAttributes xAttrs2 = new XmlAttributes();

        // define an XmlElement attribute, for a type of "String", with no namespace
        var xElt = new XmlElementAttribute(typeof(String)) { Namespace = ""};

        // add that XmlElement attribute to the 2nd bunch of attributes
        xAttrs2.XmlElements.Add(xElt);

        // add that bunch of attributes to the container for the type, and
        // specifically apply that bunch to the "Label" property on the type.
        xOver.Add(typeof(MyTypeWithNamespaces), "Label", xAttrs2);

        // instantiate a serializer with the overrides 
        XmlSerializer s3 = new XmlSerializer(typeof(MyTypeWithNamespaces), xOver);

        // serialize
        s3.Serialize(System.Console.Out, o2, ns2);

The result looks like this;

结果是这样的;

<MyTypeWithNamespaces>
  <Label>Cimsswybclaeqjh</Label>
  <Epoch>97</Epoch>
</MyTypeWithNamespaces>

You have stripped the namespaces.

您已经剥离了命名空间。

A logical question is, can you strip all namespaces from arbitrary types during serialization, without going through the explicit overrides?The answer is YES, and how to do it is in my next response.

一个合乎逻辑的问题是,您能否在序列化期间从任意类型中剥离所有名称空间,而无需通过显式覆盖?答案是肯定的,如何做在我的下一个回复中。

回答by Cheeso

This is the 2nd of two answers.

这是两个答案中的第二个。

If you want to just strip all namespaces arbitrarily from a document during serialization, you can do this by implementing your own XmlWriter.

如果您只想在序列化期间从文档中任意剥离所有名称空间,您可以通过实现您自己的 XmlWriter 来实现。

The easiest way is to derive from XmlTextWriter and override the StartElement method that emits namespaces. The StartElement method is invoked by the XmlSerializer when emitting any elements, including the root. By overriding the namespace for each element, and replacing it with the empty string, you've stripped the namespaces from the output.

最简单的方法是从 XmlTextWriter 派生并覆盖发出命名空间的 StartElement 方法。XmlSerializer 在发出任何元素(包括根)时调用 StartElement 方法。通过覆盖每个元素的命名空间,并将其替换为空字符串,您已经从输出中剥离了命名空间。

public class NoNamespaceXmlWriter : XmlTextWriter
{
    //Provide as many contructors as you need
    public NoNamespaceXmlWriter(System.IO.TextWriter output)
        : base(output) { Formatting= System.Xml.Formatting.Indented;}

    public override void WriteStartDocument () { }

    public override void WriteStartElement(string prefix, string localName, string ns)
    {
        base.WriteStartElement("", localName, "");
    }
}

Suppose this is the type:

假设这是类型:

// explicitly specify a namespace for this type,
// to be used during XML serialization.
[XmlRoot(Namespace="urn:Abracadabra")]
public class MyTypeWithNamespaces
{
    // private fields backing the properties
    private int _Epoch;
    private string _Label;

    // explicitly define a distinct namespace for this element
    [XmlElement(Namespace="urn:Whoohoo")]
    public string Label
    {
        set {  _Label= value; } 
        get { return _Label; } 
    }

    // this property will be implicitly serialized to XML using the
    // member name for the element name, and inheriting the namespace from
    // the type.
    public int Epoch
    {
        set {  _Epoch= value; } 
        get { return _Epoch; } 
    }
}

Here's how you would use such a thing during serialization:

以下是在序列化期间如何使用这样的东西:

        var o2= new MyTypeWithNamespaces { ..intializers.. };
        var builder = new System.Text.StringBuilder();
        using ( XmlWriter writer = new NoNamespaceXmlWriter(new System.IO.StringWriter(builder)))
        {
            s2.Serialize(writer, o2, ns2);
        }            
        Console.WriteLine("{0}",builder.ToString());

The XmlTextWriter is sort of broken, though. According to the reference doc, when it writes it does not check for the following:

不过,XmlTextWriter 有点坏了。根据参考文档,当它写入时,它不会检查以下内容:

  • Invalid characters in attribute and element names.

  • Unicode characters that do not fit the specified encoding. If the Unicode characters do not fit the specified encoding, the XmlTextWriter does not escape the Unicode characters into character entities.

  • Duplicate attributes.

  • Characters in the DOCTYPE public identifier or system identifier.

  • 属性和元素名称中的字符无效。

  • 不符合指定编码的 Unicode 字符。如果 Unicode 字符不适合指定的编码,则 XmlTextWriter 不会将 Unicode 字符转义为字符实体。

  • 重复属性。

  • DOCTYPE 公共标识符或系统标识符中的字符。

These problems with XmlTextWriter have been around since v1.1 of the .NET Framework, and they will remain, for backward compatibility. If you have no concerns about those problems, then by all means use the XmlTextWriter. But most people would like a bit more reliability.

XmlTextWriter 的这些问题从 .NET Framework 的 v1.1 开始就一直存在,为了向后兼容,它们将继续存在。如果您不担心这些问题,那么一定要使用 XmlTextWriter。但大多数人想要更高的可靠性。

To get that, while still suppressing namespaces during serialization, instead of deriving from XmlTextWriter, define a concrete implementation of the abstract XmlWriterand its 24 methods.

为此,在序列化期间仍然抑制命名空间的同时,不要从 XmlTextWriter 派生,而是定义抽象XmlWriter及其 24 个方法的具体实现。

An example is here:

一个例子在这里:

public class XmlWriterWrapper : XmlWriter
{
    protected XmlWriter writer;

    public XmlWriterWrapper(XmlWriter baseWriter)
    {
        this.Writer = baseWriter;
    }

    public override void Close()
    {
        this.writer.Close();
    }

    protected override void Dispose(bool disposing)
    {
        ((IDisposable) this.writer).Dispose();
    }

    public override void Flush()
    {
        this.writer.Flush();
    }

    public override string LookupPrefix(string ns)
    {
        return this.writer.LookupPrefix(ns);
    }

    public override void WriteBase64(byte[] buffer, int index, int count)
    {
        this.writer.WriteBase64(buffer, index, count);
    }

    public override void WriteCData(string text)
    {
        this.writer.WriteCData(text);
    }

    public override void WriteCharEntity(char ch)
    {
        this.writer.WriteCharEntity(ch);
    }

    public override void WriteChars(char[] buffer, int index, int count)
    {
        this.writer.WriteChars(buffer, index, count);
    }

    public override void WriteComment(string text)
    {
        this.writer.WriteComment(text);
    }

    public override void WriteDocType(string name, string pubid, string sysid, string subset)
    {
        this.writer.WriteDocType(name, pubid, sysid, subset);
    }

    public override void WriteEndAttribute()
    {
        this.writer.WriteEndAttribute();
    }

    public override void WriteEndDocument()
    {
        this.writer.WriteEndDocument();
    }

    public override void WriteEndElement()
    {
        this.writer.WriteEndElement();
    }

    public override void WriteEntityRef(string name)
    {
        this.writer.WriteEntityRef(name);
    }

    public override void WriteFullEndElement()
    {
        this.writer.WriteFullEndElement();
    }

    public override void WriteProcessingInstruction(string name, string text)
    {
        this.writer.WriteProcessingInstruction(name, text);
    }

    public override void WriteRaw(string data)
    {
        this.writer.WriteRaw(data);
    }

    public override void WriteRaw(char[] buffer, int index, int count)
    {
        this.writer.WriteRaw(buffer, index, count);
    }

    public override void WriteStartAttribute(string prefix, string localName, string ns)
    {
        this.writer.WriteStartAttribute(prefix, localName, ns);
    }

    public override void WriteStartDocument()
    {
        this.writer.WriteStartDocument();
    }

    public override void WriteStartDocument(bool standalone)
    {
        this.writer.WriteStartDocument(standalone);
    }

    public override void WriteStartElement(string prefix, string localName, string ns)
    {
        this.writer.WriteStartElement(prefix, localName, ns);
    }

    public override void WriteString(string text)
    {
        this.writer.WriteString(text);
    }

    public override void WriteSurrogateCharEntity(char lowChar, char highChar)
    {
        this.writer.WriteSurrogateCharEntity(lowChar, highChar);
    }

    public override void WriteValue(bool value)
    {
        this.writer.WriteValue(value);
    }

    public override void WriteValue(DateTime value)
    {
        this.writer.WriteValue(value);
    }

    public override void WriteValue(decimal value)
    {
        this.writer.WriteValue(value);
    }

    public override void WriteValue(double value)
    {
        this.writer.WriteValue(value);
    }

    public override void WriteValue(int value)
    {
        this.writer.WriteValue(value);
    }

    public override void WriteValue(long value)
    {
        this.writer.WriteValue(value);
    }

    public override void WriteValue(object value)
    {
        this.writer.WriteValue(value);
    }

    public override void WriteValue(float value)
    {
        this.writer.WriteValue(value);
    }

    public override void WriteValue(string value)
    {
        this.writer.WriteValue(value);
    }

    public override void WriteWhitespace(string ws)
    {
        this.writer.WriteWhitespace(ws);
    }


    public override XmlWriterSettings Settings
    {
        get
        {
            return this.writer.Settings;
        }
    }

    protected XmlWriter Writer
    {
        get
        {
            return this.writer;
        }
        set
        {
            this.writer = value;
        }
    }

    public override System.Xml.WriteState WriteState
    {
        get
        {
            return this.writer.WriteState;
        }
    }

    public override string XmlLang
    {
        get
        {
            return this.writer.XmlLang;
        }
    }

    public override System.Xml.XmlSpace XmlSpace
    {
        get
        {
            return this.writer.XmlSpace;
        }
    }        
}

Then, provide a derived class that overrides the StartElement method, as before:

然后,像以前一样,提供一个覆盖 StartElement 方法的派生类:

public class NamespaceSupressingXmlWriter : XmlWriterWrapper
{
    //Provide as many contructors as you need
    public NamespaceSupressingXmlWriter(System.IO.TextWriter output)
        : base(XmlWriter.Create(output)) { }

    public NamespaceSupressingXmlWriter(XmlWriter output)
        : base(XmlWriter.Create(output)) { }

    public override void WriteStartElement(string prefix, string localName, string ns)
    {
        base.WriteStartElement("", localName, "");
    }
}

And then use this writer like so:

然后像这样使用这个作家:

        var o2= new MyTypeWithNamespaces { ..intializers.. };
        var builder = new System.Text.StringBuilder();
        var settings = new XmlWriterSettings { OmitXmlDeclaration = true, Indent= true };
        using ( XmlWriter innerWriter = XmlWriter.Create(builder, settings))
            using ( XmlWriter writer = new NamespaceSupressingXmlWriter(innerWriter))
            {
                s2.Serialize(writer, o2, ns2);
            }            
        Console.WriteLine("{0}",builder.ToString());

Credit for this to Oleg Tkachenko.

这要归功于 Oleg Tkachenko

回答by fourpastmidnight

After reading Microsoft's documentation and several solutions online, I have discovered the solution to this problem. It works with both the built-in XmlSerializerand custom XML serialization via IXmlSerialiazble.

网上看了微软的文档和几个解决方案,找到了解决这个问题的办法。它XmlSerializer通过IXmlSerialiazble.

To wit, I'll use the same MyTypeWithNamespacesXML sample that's been used in the answers to this question so far.

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;
}

That's all to this class. Now, some objected to having an XmlSerializerNamespacesobject somewhere within their classes; but as you can see, I neatly tucked it away in the default constructor and exposed a public property to return the namespaces.

这就是这门课的全部内容。现在,有些人反对XmlSerializerNamespaces在他们的类中的某个地方有一个对象;但正如你所看到的,我巧妙地将它隐藏在默认构造函数中,并公开了一个公共属性来返回命名空间。

Now, when it comes time to serialize the class, you would use the following code:

现在,当需要序列化类时,您将使用以下代码:

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);

Once you have done this, you should get the following output:

完成此操作后,您应该获得以下输出:

<MyTypeWithNamespaces>
    <Label xmlns="urn:Whoohoo">myLabel</Label>
    <Epoch>42</Epoch>
</MyTypeWithNamespaces>

I have successfully used this method in a recent project with a deep hierachy of classes that are serialized to XML for web service calls. Microsoft's documentation is not very clear about what to do with the publicly accesible XmlSerializerNamespacesmember once you've created it, and so many think it's useless. But by following their documentation and using it in the manner shown above, you can customize how the XmlSerializer generates XML for your classes without resorting to unsupported behavior or "rolling your own" serialization by implementing IXmlSerializable.

我在最近的一个项目中成功地使用了这种方法,该项目具有深层次的类,这些类被序列化为 XML 以进行 Web 服务调用。Microsoft 的文档并不清楚XmlSerializerNamespaces一旦您创建了可公开访问的成员如何处理它,因此许多人认为它没有用。但是通过遵循他们的文档并以上面显示的方式使用它,您可以自定义 XmlSerializer 如何为您的类生成 XML,而无需诉诸不受支持的行为或通过实现IXmlSerializable.

It is my hope that this answer will put to rest, once and for all, how to get rid of the standard xsiand xsdnamespaces generated by the XmlSerializer.

我希望这个答案会平息,一劳永逸,如何摆脱标准的xsi,并xsd通过所产生的命名空间XmlSerializer

UPDATE: I just want to make sure I answered the OP's question about removing all namespaces. My code above will work for this; let me show you how. Now, in the example above, you really can't get rid of all namespaces (because there are two namespaces in use). Somewhere in your XML document, you're going to need to have something like xmlns="urn:Abracadabra" xmlns:w="urn:Whoohoo. If the class in the example is part of a larger document, then somewhere above a namespace must be declared for either one of (or both) Abracadbraand Whoohoo. If not, then the element in one or both of the namespaces must be decorated with a prefix of some sort (you can't have two default namespaces, right?). So, for this example, Abracadabrais the defalt namespace. I could inside my MyTypeWithNamespacesclass add a namespace prefix for the Whoohoonamespace like so:

更新:我只是想确保我回答了 OP 关于删除所有命名空间的问题。我上面的代码适用于此;让我来告诉你怎么做。现在,在上面的示例中,您确实无法摆脱所有命名空间(因为有两个命名空间正在使用)。在 XML 文档的某处,您将需要有类似xmlns="urn:Abracadabra" xmlns:w="urn:Whoohoo. 如果在示例类是一个更大的文档的一部分,然后某处命名空间上方必须声明为中的任一个(或两者)AbracadbraWhoohoo。如果没有,那么一个或两个命名空间中的元素必须用某种前缀装饰(你不能有两个默认命名空间,对吧?)。所以,对于这个例子,Abracadabra是 defalt 命名空间。我可以在我的MyTypeWithNamespaces类中为命名空间添加一个命名空间前缀,Whoohoo如下所示:

public MyTypeWithNamespaces
{
    this._namespaces = new XmlSerializerNamespaces(new XmlQualifiedName[] {
        new XmlQualifiedName(string.Empty, "urn:Abracadabra"), // Default Namespace
        new XmlQualifiedName("w", "urn:Whoohoo")
    });
}

Now, in my class definition, I indicated that the <Label/>element is in the namespace "urn:Whoohoo", so I don't need to do anything further. When I now serialize the class using my above serialization code unchanged, this is the output:

现在,在我的类定义中,我指出该<Label/>元素在 namespace 中"urn:Whoohoo",所以我不需要再做任何事情了。当我现在使用上面的序列化代码不变地序列化类时,这是输出:

<MyTypeWithNamespaces xmlns:w="urn:Whoohoo">
    <w:Label>myLabel</w:Label>
    <Epoch>42</Epoch>
</MyTypeWithNamespaces>

Because <Label>is in a different namespace from the rest of the document, it must, in someway, be "decorated" with a namespace. Notice that there are still no xsiand xsdnamespaces.

因为<Label>它与文档的其余部分位于不同的命名空间中,所以它必须以某种方式用命名空间“装饰”。请注意,仍然没有xsixsd命名空间。

回答by Tejas

XmlSerializer sr = new XmlSerializer(objectToSerialize.GetType());
TextWriter xmlWriter = new StreamWriter(filename);
XmlSerializerNamespaces namespaces = new XmlSerializerNamespaces();
namespaces.Add(string.Empty, string.Empty);
sr.Serialize(xmlWriter, objectToSerialize, namespaces);