web-dev-qa-db-fra.com

Puis-je obliger XmlSerializer à ignorer l'espace de nom lors de la désérialisation?

Puis-je faire en sorte que XmlSerializer ignore l'espace de noms (attribut xmlns) lors de la désérialisation, de sorte que le fait que l'attribut soit ajouté ou non, ou même si l'attribut soit faux, n'a pas d'importance? Je sais que l'on fera toujours confiance à la source, donc je ne me soucie pas de l'attribut xmlns.

36
NotDan

Oui, vous pouvez indiquer à XmlSerializer d'ignorer les espaces de noms lors de la dé-sérialisation. 

Définissez un XmlTextReader qui ignore les espaces de noms. Ainsi: 

// helper class to ignore namespaces when de-serializing
public class NamespaceIgnorantXmlTextReader : XmlTextReader
{
    public NamespaceIgnorantXmlTextReader(System.IO.TextReader reader): base(reader) { }

    public override string NamespaceURI
    {
        get { return ""; }
    }
}

// helper class to omit XML decl at start of document when serializing
public class XTWFND  : XmlTextWriter {
    public XTWFND (System.IO.TextWriter w) : base(w) { Formatting= System.Xml.Formatting.Indented;}
    public override void WriteStartDocument () { }
}

Voici un exemple de la façon dont vous désérialiseriez en utilisant ce TextReader:

public class MyType1 
{
    public string Label
    {
        set {  _Label= value; } 
        get { return _Label; } 
    }

    private int _Epoch;
    public int Epoch
    {
        set {  _Epoch= value; } 
        get { return _Epoch; } 
    }        
}



    String RawXml_WithNamespaces = @"
      <MyType1 xmlns='urn:booboo-dee-doo'>
        <Label>This document has namespaces on its elements</Label>
        <Epoch xmlns='urn:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'>0</Epoch>
      </MyType1>";


    System.IO.StringReader sr;
    sr= new System.IO.StringReader(RawXml_WithNamespaces);
    var o1= (MyType1) s1.Deserialize(new NamespaceIgnorantXmlTextReader(sr));
    System.Console.WriteLine("\n\nDe-serialized, then serialized again:\n");
    s1.Serialize(new XTWFND(System.Console.Out), o1, ns);
    Console.WriteLine("\n\n");

Le résultat est comme suit: 

    <MyType1>
      <Label>This document has namespaces on its elements</Label>
      <Epoch>0</Epoch>
    </MyType1>
43
Cheeso

Si vous ne prévoyez pas d’espace de nommage, mais que l’entrée comporte des espaces de nommage, vous pouvez définir 

Namespaces = false

sur votre XmlTextReader.

15
Wolfgang Grinfeld

Réponse de Wolfgang Grinfeld (sans traitement des exceptions):

public static Message Convert(XmlDocument doc)
{
    Message obj;
    using (TextReader textReader = new StringReader(doc.OuterXml))
    {
        using (XmlTextReader reader = new XmlTextReader(textReader))
        {
            reader.Namespaces = false;
            XmlSerializer serializer = new XmlSerializer(typeof(Message));
            obj = (Message)serializer.Deserialize(reader);
        }
    }

    return obj;
}
5
klm_

Ceci a été résolu en utilisant XmlSerializer Deserialize pour lire à partir de XML au lieu de stream. De cette façon, avant que xml ne soit désérialisé, utilisez Regex pour supprimer xsi: type du xml. Était-ce faire est bibliothèque de classes portable pour la plate-forme croisée, donc n'a pas eu beaucoup d'autres options :(. Après cela, la désérialisation semble fonctionner correctement. 

Le code suivant peut aider,

public static TClass Deserialize<TClass>(string xml) where TClass : class, new()
{
    var tClass = new TClass();

    xml = RemoveTypeTagFromXml(xml);

    var xmlSerializer = new XmlSerializer(typeof(TClass));
    using (TextReader textReader = new StringReader(xml))
    {
        tClass = (TClass)xmlSerializer.Deserialize(textReader);
    }
    return tClass;
}

public static string RemoveTypeTagFromXml(string xml)
{
    if (!string.IsNullOrEmpty(xml) && xml.Contains("xsi:type"))
    {
        xml = Regex.Replace(xml, @"\s+xsi:type=""\w+""", "");
    }
    return xml;
}
0
Abhimanyu Shukla

Cela n'ignore pas l'espace de nom, mais l'attend à la place. J'essayais de faire la même chose que vous, mais j'ai depuis ajouté une validation avec un XSD et l'espace de noms est maintenant requis. Donc, voici ce que j'attendais d'un espace de noms. https://stackoverflow.com/a/7730989/1856992

0
thinklarge