it-swarm.com.de

Kann ich XmlSerializer dazu bringen, den Namespace bei der Deserialisierung zu ignorieren?

Kann ich XmlSerializer dazu veranlassen, den Namespace (xmlns-Attribut) bei der Deserialisierung zu ignorieren, sodass es egal ist, ob das Attribut hinzugefügt wird oder nicht oder sogar, wenn das Attribut falsch ist? Ich weiß, dass der Quelle immer vertraut wird, also kümmere ich mich nicht um das xmlns-Attribut.

36
NotDan

Ja, Sie können den XmlSerializer anweisen, Namespaces während der Deserialisierung zu ignorieren. 

Definieren Sie einen XmlTextReader, der Namespaces ignoriert. So wie: 

// 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 () { }
}

Hier ein Beispiel, wie Sie mit diesem TextReader die Serialisierung durchführen würden:

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

Das Ergebnis ist so: 

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

Wenn Sie keinen Namespace erwarten, die Eingabe jedoch Namespaces hat, können Sie dies festlegen 

Namespaces = false

auf Ihrem XmlTextReader.

15

Erweiterte Antwort von Wolfgang Grinfeld (ohne Ausnahmebehandlung):

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_

Dies wurde durch Verwendung von XmlSerializer Deserialize zum Lesen von XML anstelle von Stream gelöst. Auf diese Weise, bevor xml deserialisiert wird, verwenden Sie Regex, um xsi: type aus dem xml zu entfernen. War dies die Portable Class Library für Cross Platform, so hatte es nicht viele andere Möglichkeiten :(. Danach scheint die Deserialisierung gut zu funktionieren. 

Folgender Code kann helfen,

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

Dabei wird der Namespace nicht ignoriert, sondern erwartet. Ich habe versucht, dasselbe zu tun wie Sie, aber ich habe die Validierung mithilfe einer XSD hinzugefügt und der Namespace ist nun erforderlich. Daher habe ich hier einen Namespace erwartet. https://stackoverflow.com/a/7730989/1856992

0
thinklarge