Пропуск всех пространств имен xsi и xsd при сериализации объекта в .NET?


132

Код выглядит так:

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, я могу следовать ответу из раздела Как сериализовать объект в XML без получения xmlns = ”…”? ,

Я хочу, чтобы мой тег сообщения был <message>(без каких-либо атрибутов пространства имен). Как я могу это сделать?


2
Я знаю, что вы думаете, что это может улучшить ваш xml, но предоставление пространств имен и соответствующих xsd - лучшая практика.

2
Мне нужен мой xml только как <message>, я говорю об исключении пространств имен xmlns: xsi и xmlns: xsd.
NetSide,

5
Для справки: В общем, это глупая ошибка. Пространства имен существуют не просто так, и их удаление все сломает. Такие вещи, как десериализация.
Джон Сондерс,

66
Обратите внимание, что иногда это не глупо и не ошибка. Например, может потребоваться сгенерировать фрагменты документа и собрать их позже. Лично мне нужно было сгенерировать много похожих и очень больших документов. Все они имели одинаковые большие детали глубоко внутри дерева. Поэтому мне пришлось заранее сгенерировать инвариантные части и вставить их в виде байтовых массивов при создании документов. Поэтому, чтобы сделать вывод более читаемым и меньшим, мне нужно было опустить некоторые объявления пространств имен во внутренних частях, потому что они существовали на более высоких уровнях.
Дмитрий Ташкинов

Ответы:


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

2
Я просто хотел бы добавить, что удаление пространства имен по умолчанию может иметь непредвиденные последствия: например, если вы используете атрибут XmlInclude для сериализации производных типов, пространства имен будут добавлены к каждому из этих элементов, хотите вы этого или нет, потому что они необходимы для десериализации
Томас Левеск

3
Кроме того, это не удаляет все пространства имен xml, как задан вопрос. Он удаляет только пространства имен xsi и xsd, как указано в вопросе stackoverflow.com/questions/258960 , который также упоминается в этом вопросе.
Cheeso

1
Также не поддерживается MS, как упоминалось в моем собственном ответе. Это не всегда работает, особенно когда ваш тип может использоваться с другими, у которых есть пространства имен.
fourpastmidnight

@ThomasLevesque, как удалить пространство имен по умолчанию при использовании атрибута XmlInclude?
Jeson Martajaya

4
Может быть сокращено доs.Serialize(writer, objectToSerialize, new XmlSerializerNamespaces(new[] { XmlQualifiedName.Empty }));
Xeevis

27

Это второй из двух ответов.

Если вы хотите просто произвольно удалить все пространства имен из документа во время сериализации, вы можете сделать это, реализовав свой собственный 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 в некотором роде сломан. Согласно справочному документу , когда он пишет, он не проверяет следующее:

  • Недопустимые символы в именах атрибутов и элементов.

  • Символы Юникода, не соответствующие указанной кодировке. Если символы Юникода не соответствуют указанной кодировке, XmlTextWriter не преобразует символы Юникода в символьные сущности.

  • Повторяющиеся атрибуты.

  • Символы в общедоступном идентификаторе DOCTYPE или системном идентификаторе.

Эти проблемы с XmlTextWriter существуют с версии 1.1 .NET Framework, и они останутся для обратной совместимости. Если вас не беспокоят эти проблемы, непременно используйте 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());

В этом заслуга Олега Ткаченко .


3
Я обнаружил, что мне также нужно переопределить, LookupPrefix(string ns)чтобы всегда возвращать пустую строку, чтобы удалить все объявления схемы.
Кевин Брок,

Технически это не отвечает на вопрос - вы используете XmlTextWriter, а не XmlWriter. Я замечаю, потому что хочу использовать XmlWriter для XmlWriterSettings, который я могу использовать с ним.
Abacus

@ Абак, ты читал код? Он использует XmlWriter и XmlWriterSettings .
Cheeso

моя проблема, я, должно быть, пропустил это.
Abacus

Отличный ответ, в дополнение к добавленному методу из @KevinBrock мне также нужно было перегрузить атрибут <! - language: lang-cs -> WriteStartAttribute (строковый префикс, строка localName, строка ns), прежде чем мой код удалит все Пространства имен. Также стоит отметить, что префиксы моего пространства имен менялись с b2p1 на p2, что заставило меня проверить другие методы с использованием префиксов.
Мабдулла

15

Прочитав документацию 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 для вызовов веб-служб. В документации Microsoft не очень ясно, что делать с общедоступным XmlSerializerNamespacesучастником после его создания, и многие думают, что это бесполезно. Но, следуя их документации и используя ее описанным выше способом, вы можете настроить, как XmlSerializer генерирует XML для ваших классов, не прибегая к неподдерживаемому поведению или «собственной» сериализации путем реализации IXmlSerializable.

Я надеюсь, что этот ответ раз и навсегда положит конец тому, как избавиться от стандартных пространств xsiи xsdпространств имен, сгенерированных XmlSerializer.

ОБНОВЛЕНИЕ: я просто хочу убедиться, что ответил на вопрос OP об удалении всех пространств имен. Мой код выше подойдет для этого; позвольте мне показать вам, как это сделать. Теперь, в приведенном выше примере, вы действительно не можете избавиться от всех пространств имен (потому что используются два пространства имен). Где-то в вашем XML-документе вам понадобится что-то вроде xmlns="urn:Abracadabra" xmlns:w="urn:Whoohoo. Если класс в примере является частью более крупного документа, то где-то выше должно быть объявлено пространство имен для одного из (или обоих) Abracadbraи Whoohoo. Если нет, то элемент в одном или обоих пространствах имен должен быть украшен каким-либо префиксом (у вас не может быть двух пространств имен по умолчанию, верно?). Итак, в этом примере 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")
    });
}

Теперь в определении моего класса я указал, что <Label/>элемент находится в пространстве имен "urn:Whoohoo", поэтому мне больше ничего не нужно делать. Когда я сериализую класс, используя приведенный выше код сериализации без изменений, вот результат:

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

Поскольку он <Label>находится в пространстве имен, отличном от остального документа, он должен каким-то образом быть «украшен» пространством имен. Обратите внимание , что до сих пор нет xsiи xsdпространств имен.


«В документации Microsoft прямо сказано, что это не поддерживается». Хотите поделиться где?
Дэйв Ван ден Эйнде,

Дейв, как вы написали в моем ответе на аналогичный вопрос, XmlSerializer: удалите ненужные пространства имен xsi и xsd , ссылка здесь: XmlSerializerNamespaces Class .
fourpastmidnight

1
Вы по-прежнему передаете пространства имен методу Serialize. Я думал, что идея предоставить публичного участника заключалась в том, что вам не пришлось бы этого делать? Я не могу заставить его работать, не передав его методу Serialize. И, к сожалению, у меня нет доступа к этому вызову метода. Я могу установить только экземпляр XmlSerializer для использования.
Crush

Я обнаружил, что на самом деле это XmlWriterто, что содержится в, XmlMediaTypeFormatterчто заставляет пространства имен xsi и xsd в моем выводе независимо. Это влияет только на тех, кто использует WebApi по умолчанию XmlMediaTypeFormatter. Я скопировал для него исходный код и изменил его, чтобы передать свое свойство Namespaces методу Serialize, так как это необходимо для предотвращения XmlWriterавтоматического добавления двух значений по умолчанию. Смотрите этот ответ
Crush

@crush, ответ, на который вы ссылаетесь, вводит в заблуждение - не ошибается, но не все его утверждения верны. Если вы посмотрите на первый фрагмент кода в моем ответе, вы увидите комментарий, в котором явно указано, как работает XmlSerializer, когда вы открываете публичный член типа, XmlSerializerNamespacesукрашенный XmlNamespacesDeclarationAttribute. Это было взято непосредственно из MSDN и, по сути, использует эти объявленные пространства имен вместо пространств по умолчанию, предоставляемых XmlSerializer.
fourpastmidnight

6

Это первый из двух моих ответов на вопрос.

Если вам нужен точный контроль над пространствами имен - например, если вы хотите опустить некоторые из них, но не другие, или если вы хотите заменить одно пространство имен другим, вы можете сделать это с помощью 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>

Обратите внимание, что для корневого элемента есть пространство имен по умолчанию, а также отдельное пространство имен для элемента «Label». Эти пространства имен были продиктованы атрибутами, украшающими тип, в приведенном выше коде.

Платформа сериализации Xml в .NET включает возможность явно переопределить атрибуты, украшающие фактический код. Вы делаете это с помощью класса 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>

Вы удалили пространства имен.

Возникает логичный вопрос: можно ли удалить все пространства имен из произвольных типов во время сериализации, не выполняя явных переопределений? Ответ - ДА, и как это сделать - в моем следующем ответе.


6
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);
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.