Я хочу сериализовать XML-документы из сторонней службы, которые представлены в любом из двух форматов (я добавил отступы для облегчения чтения):
1.
<STADMessage>Invalid Request, no content provided!</STADMessage>
2.
<STADMessage>
<Message>Invalid Request, see log for detail using reference: ASDFL210359872305982035</Message>
</STADMessage>
Прямо сейчас я взламываю XML-документ, прежде чем он будет сериализован с помощью следующего кода
xmlDocument.Replace("<STADMessage><Message>", "<STADMessages><Message>")
.Replace("</Message></STADMessage>", "</Message></STADMessages>");
Фрагмент сериализованного класса
[XmlElement(ElementName = "STADMessage", IsNullable = true)]
public string STADMessage { get; set; }
[XmlArray(ElementName = "STADMessages", IsNullable = true)]
[XmlArrayItem("Message", typeof(string))]
public List<string> STADMessages { get; set; }
Есть способ чище?





Если вы жестяная банка заставите их изменить ее на правильную структуру, как рекомендует @FrankerZ, это было бы идеально. Если не можете, надеюсь, это поможет.
Вы можете учесть это изменение с помощью настраиваемого объекта сериализации, который десериализует по-разному зависит от типа входящего узла.
Измените тип свойства STADMessage на пользовательский тип (я назову его STADMessage, черт возьми):
[XmlElement(ElementName = "STADMessage", IsNullable = true)]
public STADMessage STADMessage { get; set; }
А вот и класс STADMessage:
public class MySTADMessage : IXmlSerializable
{
public string Message { get; set; }
public XmlSchema GetSchema()
{
return null;
}
public void ReadXml(XmlReader reader)
{
// IsNullable = true is ignored, apparently. You won't get an actual
// null for properties deserialized this way because the serializer
// already created an instance of this class.
if (reader.GetAttribute("nil", XmlSchema.InstanceNamespace) == "true")
return;
reader.ReadStartElement();
while (reader.NodeType == XmlNodeType.Whitespace)
reader.Read();
if (reader.NodeType == XmlNodeType.Text)
{
Message = reader.ReadContentAsString();
}
else if (reader.NodeType == XmlNodeType.Element)
{
if (reader.Name != "Message")
throw new Exception("Unexpected element name.");
reader.ReadStartElement();
if (reader.NodeType == XmlNodeType.Text)
{
Message = reader.ReadContentAsString();
}
else
{
throw new Exception("Unexpected node type.");
}
reader.ReadEndElement();
}
else
{
throw new Exception("Unexpected node type.");
}
reader.ReadEndElement();
}
public void WriteXml(XmlWriter writer)
{
// Not having the extra Message element is simpler.
writer.WriteString(Message);
}
}
Это грубо, это не довольно правильно реализует IXmlSerializable по сегодняшним стандартам, и, вероятно, не учитывает все, но это должно помочь вам начать.
Ух, это так некрасиво с их стороны делать это со своей стороны. Вы должны отправить запрос их команде разработчиков и научить их, что такое стандартизация.