【问题标题】:Omitting all xsi and xsd namespaces when serializing an object in .NET?在 .NET 中序列化对象时忽略所有 xsi 和 xsd 命名空间?
【发布时间】:2010-10-12 04:10:36
【问题描述】:

代码如下所示:

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

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

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

要删除 xsi 和 xsd 命名空间,我可以按照How to serialize an object to XML without getting xmlns=”…”? 的答案。

我希望我的消息标记为&lt;message&gt;(没有任何命名空间属性)。我该怎么做?

【问题讨论】:

  • 我知道您认为这可能会使您的 xml 看起来更好,但提供命名空间和相应的 xsd 是更好的做法。
  • 我只希望我的 xml 作为 ,我说的是省略 xmlns:xsi 和 xmlns:xsd 命名空间。
  • 郑重声明:总的来说,这是一个愚蠢的错误。命名空间的存在是有原因的,删除它们会破坏一切。诸如反序列化之类的事情。
  • 请注意,有时这并不愚蠢,也不是错误。例如,可能需要生成文档片段并稍后将它们组合在一起。就我个人而言,我需要生成许多类似且非常大的文档。它们在树的深处都有相同的大部分。所以我必须事先生成不变部分,并在生成文档时将它们作为字节数组插入。因此,为了使输出更具可读性和更小,我需要省略内部部分中的一些命名空间声明,因为它们存在于更高级别。
  • @JohnSaunders 我很满意 .NET 添加命名空间以实现兼容性。问题是 .NET 并没有始终如一地为每个创建的元素添加命名空间。所以,你最终不得不惹他们,尽管对它很好

标签: c# .net xml-serialization


【解决方案1】:
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);

【讨论】:

    【解决方案2】:

    在网上阅读了微软的文档和几个解决方案后,我发现了这个问题的解决方案。它适用于内置的XmlSerializer 和通过IXmlSerialiazble 的自定义XML 序列化。

    也就是说,我将使用迄今为止在此问题的答案中使用的相同 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 生成的标准xsixsd 命名空间。

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

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

    现在,在我的类定义中,我指出&lt;Label/&gt; 元素在命名空间"urn:Whoohoo" 中,所以我不需要做任何进一步的事情。当我现在使用上面的序列化代码来序列化类时,输出如下:

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

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

    【讨论】:

    • “Microsoft 的文档明确表示它不受支持。”想在哪里分享?
    • 戴夫,正如您在我对类似问题的回答中发布的那样,XmlSerializer: remove unnecessary xsi and xsd namespaces,链接在这里:XmlSerializerNamespaces Class
    • 您仍在将命名空间传递给 Serialize 方法。我认为提供公共成员的想法是您不必这样做?如果不将它传递给 Serialize 方法,我无法让它工作。不幸的是,我无权访问该方法调用。我只能设置要使用的 XmlSerializer 实例。
    • 我发现实际上是 XmlWriter 包含在 XmlMediaTypeFormatter 中,无论如何都会强制 xsi 和 xsd 命名空间进入我的输出。这只会影响那些使用 WebApi 的默认 XmlMediaTypeFormatter 的用户。我复制了它的源代码,并修改它以将我的 Namespaces 属性传递给 Serialize 方法,因为它需要防止 XmlWriter 自动添加两个默认值。见this answer
    • @crush,您链接到的那个答案具有误导性——没有错,但它的断言并不完全正确。如果您查看我的答案中的第一个代码 sn-p,您将看到一条注释,其中明确说明了当您公开使用 XmlNamespacesDeclarationAttribute 装饰的 XmlSerializerNamespaces 类型的公共成员时 XmlSerializer 如何工作。这是从 MSDN 直接 获取的,基本上使用那些声明的命名空间来代替 XmlSerializer 提供的默认命名空间。
    【解决方案3】:
    ...
    XmlSerializer s = new XmlSerializer(objectToSerialize.GetType());
    XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
    ns.Add("","");
    s.Serialize(xmlWriter, objectToSerialize, ns);
    

    【讨论】:

    • 我想补充一点,删除默认命名空间可能会产生意想不到的后果:例如,如果您使用 XmlInclude 属性序列化派生类型,则命名空间将被添加到这些元素中的每一个,无论是否不管你想要与否,因为它们是反序列化所必需的
    • 另外,正如问题所问的那样,这不会删除 all xml 命名空间。它仅删除 xsi 和 xsd 命名空间,如问题 stackoverflow.com/questions/258960 中所述,this 问题中也引用了该名称。
    • 我自己的回答中提到的MS也不支持。它并不总是有效,尤其是当您的类型可能与其他确实具有命名空间的类型一起使用时。
    • 感谢 Thomas Levesque 的回答。因为我也不是住在一切都符合最佳实践的象牙塔里,所以这很好地解决了我的问题。
    • 可简写为s.Serialize(writer, objectToSerialize, new XmlSerializerNamespaces(new[] { XmlQualifiedName.Empty }));
    【解决方案4】:

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

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

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

    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, "");
        }
    }
    

    假设这是类型:

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

    在序列化过程中你会如何使用这样的东西:

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

    不过,XmlTextWriter 有点坏了。根据reference doc,它在写入时不会检查以下内容:

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

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

    • 重复属性。

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

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

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

    这里有一个例子:

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

    然后,像以前一样,提供一个覆盖 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, "");
        }
    }
    

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

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

    将此归功于Oleg Tkachenko

    【讨论】:

    • 我发现我还需要重写LookupPrefix(string ns) 以始终返回一个空字符串以删除所有架构声明。
    • 这在技术上并不能回答问题 - 您使用的是 XmlTextWriter,而不是 XmlWriter。我注意到是因为我想使用 XmlWriter,因为我可以使用 XmlWriterSettings。
    • @Abacus 你读过代码吗?它使用XmlWriter XmlWriterSettings
    • 我的错,我一定错过了。
    • 很好的答案,除了 @KevinBrock 添加的方法之外,我还需要重载 WriteStartAttribute(string prefix, string localName, string ns)在我的代码删除所有命名空间之前。另外值得注意的是,我的命名空间前缀从 b2p1 更改为 p2,这导致我检查使用前缀的其他方法。
    【解决方案5】:

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

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

    假设你有这个类型定义:

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

    还有这个序列化伪代码:

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

    你会得到类似这样的 XML:

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

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

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

    结果如下所示;

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

    你已经剥离了命名空间。

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

    【讨论】:

      猜你喜欢
      • 2012-09-17
      • 2015-04-03
      • 1970-01-01
      • 2010-10-20
      • 2021-02-17
      • 2016-11-21
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多