Пропускаючи всі простори імен 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 був лише як <повідомлення>, я кажу про пропущення 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, як згадується у моїй власній відповіді. Це не завжди працює, особливо коли ваш тип може використовуватися з іншими, у яких є простори імен.
чотирипаночі

@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 начебто зламаний. Згідно з посилальним документом , коли він пише, він не перевіряє:

  • Недійсні символи в іменах атрибутів та елементів.

  • Символи Unicode, які не відповідають заданому кодуванню. Якщо символи Unicode не відповідають заданому кодуванню, XmlTextWriter не уникає символів Unicode в сукупності символів.

  • Дублікати атрибутів.

  • Символи в загальнодоступному ідентифікаторі DOCTYPE або ідентифікаторі системи.

Ці проблеми з XmlTextWriter існують з v1.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 .
Чесо

моя погана, я, мабуть, це пропустив.
Абак

Чудовий відповідь, Крім доданого методу від @KevinBrock, мені також потрібно було перевантажити <! - language: lang-cs -> WriteStartAttribute (префікс рядка, string localName, string 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.

ОНОВЛЕННЯ: Я просто хочу переконатися, що я відповів на питання ОП про видалення всіх просторів імен. Мій код вище буде працювати для цього; дозвольте мені показати, як. Тепер у наведеному вище прикладі ви дійсно не можете позбутися всіх просторів імен (тому що використовуються два простори імен). Десь у вашому документі 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 .
чотирипаночі

1
Ви все ще передаєте простори імен методу Serialize. Я думав, що ідея надання громадського члена полягала в тому, що вам цього не доведеться робити? Я не можу змусити його працювати, не переходячи його до методу Serialize. І, на жаль, у мене немає доступу до цього виклику методу. Я можу встановити для використання лише екземпляр XmlSerializer.
розчавити

Я виявив, що це насправді те, XmlWriterщо міститься в тому, XmlMediaTypeFormatterщо змушує простори імен xsi та xsd у моєму виході незалежно. Це впливає лише на тих, хто використовує за замовчуванням WebApi XmlMediaTypeFormatter. Я скопіював вихідний код для цього та змінив його, щоб передати своє властивість Namespaces методу Serialize, як це потрібно для запобігання XmlWriterавтоматичного додавання двох значень за замовчуванням. Дивіться цю відповідь
розчав

@crush, ця відповідь, з якою ви пов’язані, вводить в оману - не помиляється, але всі його твердження не всі правильні. Якщо ви подивитесь на перший фрагмент коду в моїй відповіді, ви побачите коментар, який прямо вказує, як працює XmlSerializer, коли ви виставляєте публічний член типу, XmlSerializerNamespacesприкрашений XmlNamespacesDeclarationAttribute. Це було взято безпосередньо з MSDN і по суті використовує ті оголошені простори імен замість стандартних, які надає XmlSerializer.
чотирипаночі

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>

Зауважте, що на кореневому елементі є простір імен за замовчуванням, а також на елементі "Мітка" є окрема область імен. Ці простори імен були продиктовані атрибутами, що прикрашають тип, у коді вище.

Рамка серіалізації 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.