views:

138

answers:

5

Hi,

I want to deserialize an xml file which has to be just in this form

<Basket>
  <Fruit>Apple</Fruit>
  <Fruit>Orange</Fruit>
  <Fruit>Grapes</Fruit>
</Basket>

Out of the examples I read on internet the least possible format I could find was the following

<Basket>
  <FruitArray>
    <Fruit>Apple</Fruit>
  </FruitArray>
  <FruitArray>
    <Fruit>Orange</Fruit>
  </FruitArray>
  <FruitArray>
    <Fruit>Grapes</Fruit>
  </FruitArray>
</Basket>

and that has the following deserialization class for converting it into a class object.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace XMLSerialization_Basket
{
    [System.Xml.Serialization.XmlRootAttribute("Basket", Namespace = "BasketNamespace", IsNullable = false)]
    public class Basket
    {
        /// <remarks/>
        [System.Xml.Serialization.XmlElementAttribute("FruitArray")]
        public FruitArray[] objFruitArray;
    }

    /// <remarks/>
    [System.Xml.Serialization.XmlTypeAttribute(Namespace = "BasketNamespace")]
    public class FruitArray
    {

        /// <remarks/>
        private string _Fruit;

        public string Fruit
        {

            get { return _Fruit; }
            set { _Fruit = value; }
        }
    }


}

Can I add something like the following directly under top class

    private string _Fruit;

    public string Fruit
    {

        get { return _Fruit; }
        set { _Fruit = value; }
    }

and avoid the array nesting?

my goal is to deserialize an xml of following format

<Basket>
  <Fruit>Apple</Fruit>
  <Fruit>Orange</Fruit>
  <Fruit>Grapes</Fruit>
</Basket>
+1  A: 

You should just need:

public class Basket {
    private List<string> fruits = new List<string>();
    [XmlElement("Fruit")]
    public List<string> Fruits {get {return fruits;}}
}
Marc Gravell
+1  A: 

With all respect I would modify my XML and object to deserialize into to the following.

Here is the C# (Should compile ;))

 using System.Xml.Serialization;
    using System.Xml.Schema;
    [XmlRootAttribute(Namespace = "", IsNullable = false)]
    public class Basket
    {
        [XmlArrayAttribute("Fruits", Form = XmlSchemaForm.Unqualified)]
        [XmlArrayItemAttribute("Fruit", typeof(string), Form = XmlSchemaForm.Unqualified)]
        public List<string> _items;
    }

Here is the XML

<Basket> 
  <Fruits> 
    <Fruit>Apple</Fruit> 
    <Fruit>Orange</Fruit> 
    <Fruit>Grapes</Fruit> 
  </Fruits> 
</Basket> 
Jonathan
A: 
[XmlRoot("Basket")]
class Basket : List<Fruit>
{

}

[XmlRoot("Fruit")]
class Fruit
{
    [XmlText]
    string Value { get; set; }
}

Or using LINQ to XML:

public void Serialize(Basket b)
{
    XElement _root = new XElement("Basket", 
        b.Select(
            f => new XElement("Fruit", 
                new XText(f.Value))));

    _root.Save("file.xml");
}

public void Deserialize()
{
    Basket b = new Basket();

    XElement _root = XElement.Load("file.xml");
    foreach(XElement fruit in _root.Descendants("Fruit"))
    {
        Fruit f = new Fruit();
        f.Value = fruit.Value;
        basket.Add(f);
    }
}
Aren
A: 

The previous post absolutely worked...

public class Basket { 
    private List<string> fruits = new List<string>(); 
    [XmlElement("Fruit")] 
    public List<string> Fruits {get {return fruits;}} 
} 

I put together the following test rig and it was able to read the stated XML with no problem.

var doc = new XmlDocument();
doc.Load("TheFile.xml");

var basket = XmlDeserialize<Basket>(doc.OuterXml);

public static T XmlDeserialize<T>(string serializedContent)
{
    T returnValue;

    if (String.IsNullOrEmpty(serializedContent))
    {
        returnValue = default(T);
    }
    else
    {
        var deSerializer = new XmlSerializer(typeof(T));
        var stringReader = new StringReader(serializedContent);

        try
        {
            returnValue = (T)deSerializer.Deserialize(stringReader);
        }
        catch (InvalidOperationException)
        {
            returnValue = default(T);
        }
    }

    return returnValue;
}
JoeGeeky
A: 

This is what the xml schema should look like:

<?xml version="1.0" encoding="utf-8"?>
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema"&gt;
  <xs:element name="Basket">
    <xs:complexType>
      <xs:sequence>
        <xs:element maxOccurs="unbounded" name="Fruit" type="xs:string" />
      </xs:sequence>
    </xs:complexType>
  </xs:element>
</xs:schema>

If you save the xsd (let's just call it sample.xsd) and run xsd with the following parameters:

xsd.exe /c /n:BasketOfFruits sample.xsd

You will have this class:

namespace BasketOfFruits {
    using System.Xml.Serialization;


    /// <remarks/>
    [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "2.0.50727.1432")]
    [System.SerializableAttribute()]
    [System.Diagnostics.DebuggerStepThroughAttribute()]
    [System.ComponentModel.DesignerCategoryAttribute("code")]
    [System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)]
    [System.Xml.Serialization.XmlRootAttribute(Namespace="", IsNullable=false)]
    public partial class Basket {

        private string[] fruitField;

        /// <remarks/>
        [System.Xml.Serialization.XmlElementAttribute("Fruit")]
        public string[] Fruit {
            get {
                return this.fruitField;
            }
            set {
                this.fruitField = value;
            }
        }
    }
}

Here's a sample program to demonstrate:

using System;
using System.Text;
using System.Xml;
using System.Xml.Serialization;
using BasketOfFruits;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            Basket myBasket = new Basket();
            myBasket.Fruit = new string[] { "Apple", "Orange", "Grapes" };

            XmlSerializer xs = new XmlSerializer(typeof(Basket));            
            XmlSerializerNamespaces emptyNamespace = new XmlSerializerNamespaces();
            emptyNamespace.Add(String.Empty, String.Empty);

            StringBuilder output = new StringBuilder();

            XmlWriter writer = XmlWriter.Create(output, 
                new XmlWriterSettings { OmitXmlDeclaration = true, Indent = true });
            xs.Serialize(writer, myBasket, emptyNamespace);

            Console.WriteLine(output.ToString());

            // pause program execution to review results...
            Console.WriteLine("Press enter to exit");
            Console.ReadLine();
        }
    }
}

Which will serialize to this:

<Basket>
  <Fruit>Apple</Fruit>
  <Fruit>Orange</Fruit>
  <Fruit>Grapes</Fruit>
</Basket>
code4life