Можно ли заставить XmlSerializer игнорировать пространство имен при десериализации? - PullRequest
38 голосов
/ 15 мая 2009

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

Ответы [ 6 ]

44 голосов
/ 17 мая 2009

Да, вы можете указать 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>
19 голосов
/ 29 июля 2015

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

Пространства имен = false

в вашем XmlTextReader.

8 голосов
/ 22 марта 2017

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

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;
}
0 голосов
/ 22 июня 2015

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

0 голосов
/ 22 августа 2013

Решено это с помощью 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 голосов
/ 15 мая 2009

Зачем пытаться заставить XmlSerializer забыть, как работает XML? Факт XML заключается в том, что два элемента с одинаковым именем, но разными пространствами имен являются разными элементами.

Если вы хотите обработать XML, у которого нет пространств имен, вам следует предварительно обработать его, чтобы удалить пространства имен, и затем передать его сериализатору.

...