it-swarm.com.ru

Можно ли заставить XmlSerializer игнорировать пространство имен при десериализации?

Можно ли заставить XmlSerializer игнорировать пространство имен (атрибут xmlns) при десериализации, чтобы не имело значения, добавлен атрибут или нет, или даже если атрибут является поддельным? Я знаю, что источнику всегда будут доверять, поэтому мне нет дела до атрибута xmlns.

36
NotDan

Да, вы можете указать XmlSerializer игнорировать пространства имен во время десериализации. 

Определите XmlTextReader, который игнорирует пространства имен. Вот так: 

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

Вот пример того, как вы бы десериализовали с помощью этого 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");

Результат примерно так: 

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

Если вы не ожидаете пространства имен, но вход имеет пространства имен, вы можете установить 

Пространства имен = ложь

на вашем XmlTextReader.

15
Wolfgang Grinfeld

Расширенный ответ Вольфганга Гринфельда (без обработки исключений):

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_

Решил это с помощью XmlSerializer Deserialize для чтения из xml вместо потока. Таким образом, перед десериализацией xml, используйте Regex для удаления xsi: type из xml. Делал это Портативная библиотека классов для кроссплатформенности, поэтому не было много других опций :(. После этого десериализация, кажется, работает нормально. 

Следующий код может помочь,

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

Это не игнорирует пространство имен, а ожидает его. Я пытался сделать то же самое, что и вы, но с тех пор я добавил валидацию с использованием XSD, и теперь требуется пространство имен. Итак, вот что я привык ожидать от пространства имен. https://stackoverflow.com/a/7730989/1856992

0
thinklarge