Search code examples
xmlxmlserializer

XMLSerializer - Why is there an extra child layer while serializing?


I'm serializing a complex C# object to XML document using XMLSerializer. The issue I'm facing is that after serializing, I'm getting an extra layer of child container that shouldn't be there. I'm not sure how it is getting serialized as. My object structure is follows:

[XmlRoot(ElementName = "order")]
public class order
{
    [XmlElement(ElementName = "orderNumber")]
    public string OrderNumber { get; set; }
    [XmlElement(ElementName = "products")]
    public Products Products { get; set; }
}

[XmlRoot(ElementName = "products")]
public class Products
{
    [XmlElement(ElementName = "product")]
    public List<Product> Product { get; set; }
}

[XmlRoot(ElementName = "product")]
public class Product
{
    [XmlElement(ElementName = "quantity")]
    public decimal Quantity { get; set; }
    [XmlElement(ElementName = "part")]
    public string part { get; set; }
   [XmlElement(ElementName = "unitPrice")]
    public decimal UnitPrice { get; set; }
}

I want to serlize it as order/products/product, however, it is getting serialized as order/products/product/product:

<order>
  <orderNumber>1</orderNumber>
  <products>
    <product>
      <product>
        <quantity>1</quantity>
        <part>222584</part>
        <unitPrice>5.0</unitPrice>
      </product>
      <product>
        <quantity>5</quantity>
        <part>222</part>
        <unitPrice>1.0</unitPrice>
      </product>
      <product>
        <quantity>15</quantity>
        <part>222244</part>
        <unitPrice>12.0</unitPrice>
      </product>
    </product>
  </products>
</order>

Solution

  • To remove extra tag over products then your xml serialization class should be as below:

    [XmlRoot(ElementName = "order")]
    public class order
    {
        [XmlElement(ElementName = "orderNumber")]
        public string OrderNumber { get; set; }
        [XmlElement(ElementName = "products")]
        public List<Product> Products { get; set; }
    }
    

    Current class structure is written to create hierarchy

    [XmlRoot(ElementName = "order")]
        [XmlElement(ElementName = "products")]
            [XmlElement(ElementName = "product")]
                 [XmlRoot(ElementName = "product")]<-Final Product data here
    

    Below extra layer is not required and just use List directly within your order.

    [XmlRoot(ElementName = "products")]
    public class Products
    {
        [XmlElement(ElementName = "product")]
        public List<Product> Product { get; set; }
    }