user1167362
user1167362

Reputation: 21

XML serialization of a nested object, but at the root level

I want to serialize a nested object so that its properties are at the same level as the parent object, (ie, NOT in a nested tag). Specifically: I have a C# object:

[XmlRoot(ElementName="Root")]
public class TopLevel
{
   public string topLevelProperty;
   public NestedObject nestedObj;
}

public class NestedObject
{
   string propetyOnNestedObject;
}

and I want XML like:

<root>
   <topLevelProperty>...</topLevelProperty>
   <propertyOnNestedObject>...</propertyOnNestedObject>
   <!--NOTE: propertyOnNestedObject would normally be inside a "<nested>" tag
       but I'm trying to avoid that here-->
</root> 

Is that possible?

Upvotes: 0

Views: 3216

Answers (3)

Sina Iravanian
Sina Iravanian

Reputation: 16296

You can do this with the YAXLib XML Serialization library easily:

//[XmlRoot(ElementName = "Root")]
[YAXSerializeAs("Root")]
public class TopLevel
{
    public string topLevelProperty { get; set; }
    public NestedObject nestedObj { get; set; }
}

public class NestedObject
{
    [YAXElementFor("..")]
    string propetyOnNestedObject { get; set; }
}

Note how YAXElementFor("..") attribute directs the location of serialization to the parent element. (".." looks likes parent folder in file-system paths).

Upvotes: 1

sll
sll

Reputation: 62564

As a case you can expose a nested proeprty accessor but this would make TopLevel object slightly complex. So as a case you can introduce a separate serializable wrapper to decouple such special-case wrapper from the business object itself.

[XmlRoot(ElementName="Root")] 
public class TopLevel 
{    
   public string topLevelProperty;    

   [XmlIgnore]
   public NestedObject nestedObj; 

   [XmlElement("NestedProperty")]
   public string NestedPropertyAccessor
   {
       get
       {
         return nestedObj.NestedProperty;
       }
       // set
   }
} 

OR Separate it if you need decouple serializable object from business model so you do not need complicate business object itself by specially exposed properties just to fit serialization format:

public class TopLevelSerializableWrapper
{
    public TopLevelSerializableWrapper(TopLevel businessObject)
    {
    }

    // TODO: expose all proeprties which need to serialized
}

Upvotes: 1

kev
kev

Reputation: 1124

You need to implement the IXmlSerializable Interface to override the default behaviour

[XmlRoot(ElementName = "Root")]
public class TopLevel : IXmlSerializable
{
    public string topLevelProperty;
    public NestedObject nestedObj;

    public XmlSchema GetSchema()
    {
        return null;
    }

    public void ReadXml(XmlReader reader)
    {
        //...
    }

    public void WriteXml(XmlWriter writer)
    {
        writer.WriteElementString("topLevelProperty", topLevelProperty);
        writer.WriteElementString("propertyOnNestedObject", nestedObj.propetyOnNestedObject);
    }
}

There is also a good post at CodeProject about how to implement the interface correctly: http://www.codeproject.com/Articles/43237/How-to-Implement-IXmlSerializable-Correctly

Upvotes: 1

Related Questions