RoelF
RoelF

Reputation: 7573

Deserialize part of xml into string

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

Answers (1)

Daniel J.G.
Daniel J.G.

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

Related Questions