Reputation: 7573
Is it possible to deserialize the following XML:
<MyObject><Test>Hi hello</Test><Something><Else><With><SubItems count='5'>hello world</SubItems></With></Else></Something></MyObject>
into this object:
public class MyObject {
public string Test { get; set; }
public string Something { get; set; }
}
with this as expected output (this fails at the moment with XmlException: Unexpected node type Element. ReadElementString method can only be called on elements with simple or empty content. Line 1, position 50.
)
[TestMethod]
public void TestDeserialization()
{
var s = "<MyObject><Test>Hi hello</Test><Something><Else><With><SubItems count='5'>hello world</SubItems></With></Else></Something></MyObject>";
var o = s.DeSerialize<MyObject>();
Assert.AreEqual("Hi hello", o.Test);
Assert.AreEqual("<Else><With><SubItems count='5'>hello world</SubItems></With></Else>", o.Something);
}
public static class Xml
{
public static T DeSerialize<T>(this string xml) where T : new()
{
if (String.IsNullOrEmpty(xml))
{
return new T();
}
var xmlSer = new XmlSerializer(typeof(T));
using (var stream = new StringReader(xml))
return (T)xmlSer.Deserialize(stream);
}
}
Upvotes: 2
Views: 810
Reputation: 34992
One option could be implementing IXmlSerializable
so you manually read the inner Xml into the Something
property:
public class MyObject: IXmlSerializable
{
public string Test { get; set; }
public string Something { get; set; }
public System.Xml.Schema.XmlSchema GetSchema() { return null; }
public void ReadXml(System.Xml.XmlReader reader)
{
if (reader.MoveToContent() == XmlNodeType.Element && reader.LocalName == "MyObject")
{
Test = reader["Test"];
if (reader.ReadToDescendant("Something"))
{
Something = reader.ReadInnerXml();
}
}
}
public void WriteXml(System.Xml.XmlWriter writer)
{
throw new NotImplementedException();
}
}
public static class Program
{
public static void Main()
{
var myObjectXmlString = "<MyObject><Test>Hi hello</Test><Something><Else><With><SubItems count='5'>hello world</SubItems></With></Else></Something></MyObject>";
var myObject =(MyObject) new XmlSerializer(typeof(MyObject)).Deserialize(new StringReader(myObjectXmlString));
Console.WriteLine(myObject.Something);
}
}
Another option could be converting Something
into a property of type XmlElement
so the inner random piece of Xml will be serialized as Xml instead of a string (You could still retrieve it as string by getting its OuterXml):
public class MyOtherObject
{
public string Test { get; set; }
public XmlElement Something { get; set; }
public string SomethingString
{
get { return Something.OuterXml; }
}
}
public static class Program
{
public static void Main()
{
var otherObjectXmlString = "<MyOtherObject><Test>Hi hello</Test><Something><Else><With><SubItems count='5'>hello world</SubItems></With></Else></Something></MyOtherObject>";
var otherObject =(MyOtherObject) new XmlSerializer(typeof(MyOtherObject)).Deserialize(new StringReader(otherObjectXmlString));
Console.WriteLine(otherObject.SomethingString);
}
}
I have created this fiddle so you can give them a try.
Upvotes: 4