Десериализация 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"), который, при необходимости, можно доработать под другие варианты.
Сделайте общий класс
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>"))
);
и не забываем про память Динамически создаваемые сборки. Спасибо Александр
Можно использовать такой вариант.
Удаляем класс 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".