Десериализация XML c разным корневым элементом

У меня есть два xml:

<?xml version="1.0" encoding="UTF-8"?>
<ClientCreditShortInfoListType>
  <Error>
    <ErrorCode>1</ErrorCode>
    <ErrorText>Общая ошибка</ErrorText>
  </Error>
</ClientCreditShortInfoListType>
<?xml version="1.0" encoding="UTF-8"?>
<ClientCreditShortInfoList>
  <Error>
    <ErrorCode>1</ErrorCode>
    <ErrorText>Общая ошибка</ErrorText>
  </Error>
</ClientCreditShortInfoList>

Так же есть класс для сериализации:

[XmlRoot(ElementName = "ClientCreditShortInfoListType", Namespace = FindListCreditByClientIDConst.namespaceResponse)]
public class FindListCreditByClientIDResponse
{
    [XmlElement(ElementName = "Error", Namespace = FindListCreditByClientIDConst.namespaceResponse)]
    public Error Error { get; set; }
}

Есть ли способ для сериализации(десериализации) использовать один класс, и обрабатывать xml одинаковые по сути, но разным Root. В одном случае это ClientCreditShortInfoListType в другом ClientCreditShortInfoList ?


Ответы (3 шт):

Автор решения: Макс Жуков

Попробуйте подумать в сторону XmlDocument. Что-то в стиле:

XmlDocument xmlDocument = new XmlDocument();
xmlDocument.LoadXml(xmlString);
XmlNodeList xmlNodeList = xmlDocument.SelectNodes("//Error");
foreach (XmlNode xn in xmlNodeList)
{
     //обработка данных каждого тега Error удобным для вас способом
}

Где переменная xmlString - ваша xml.

В выборке используется XPath ("//Error"), который, при необходимости, можно доработать под другие варианты.

→ Ссылка
Автор решения: Aziz Umarov

Сделайте общий класс

class CreditShortInfor {
 [XmlElement(ElementName="Error")]
 Error error;     
}

public static CreditShortInfor Deserialize(XmlReader reader)
 {
    reader.MoveToContent();
    string rootName = reader.Name;
    var serializer  = new XmlSerializer(typeof(CreditShortInfor), 
        new XmlRootAttribute(rootName)
        );
    var deserialized = serializer.Deserialize(reader) as CreditShortInfor;
    return deserialized;
 }

....

var creditShortInfor  = Deserialize(XmlReader.Create(
new StringReader("<ClientCreditShortInfoListType>
<Error>
    <ErrorCode>1</ErrorCode>
    <ErrorText>Общая ошибка</ErrorText>
  </Error>
</ClientCreditShortInfoListType>"))
);

creditShortInfor  = Deserialize(XmlReader.Create(
new StringReader("<ClientCreditShortInfoList>
<Error>
    <ErrorCode>1</ErrorCode>
    <ErrorText>Общая ошибка</ErrorText>
  </Error>
</ClientCreditShortInfoList>"))
);

и не забываем про память Динамически создаваемые сборки. Спасибо Александр

→ Ссылка
Автор решения: Alexander Petrov

Можно использовать такой вариант.

Удаляем класс FindListCreditByClientIDResponse. Оставляем только класс Error.

Десериализацию проводим следующим образом:

var serializer = new XmlSerializer(typeof(Error));
Error error;

using (var xmlReader = XmlReader.Create("test.xml"))
{
    xmlReader.ReadToFollowing("Error");
    error = (Error)serializer.Deserialize(xmlReader);
}

Console.WriteLine(error.ErrorCode + " " + error.ErrorText);

Используем XmlReader. С помощью его метода ReadToFollowing пропускаем корневой элемент, вернее, все элементы перед "Error".

→ Ссылка