none
Can't read xml written by DataSet.WriteXml into C# class with xmldeserialize

    Question

  • Hi hope someone can help!

    Have been creating xml in c# and serializing it with xmlserializer and reading back in with xmldeserializer. Also have created and xsd file with inferschema. This all works well. Now I would like to read xml into a dataset so I can edit the dataset. But when I write out the DataSet with DataSet.WriteXml I can no longer deserialize it since it adds a root element of <NewDataSet>.

    How can I make this process consistent? I want to be able to read xml into a c# class.

    Thanks.

    • Moved by John Saunders Friday, May 13, 2011 3:36 PM dataset q (From:ASMX Web Services and XML Serialization)
    Friday, May 13, 2011 3:30 PM

Answers

  • Hi Fernando,

    I too am sorry you cannot answer my question. I had originally posted my question there but a moderator moved it.

    I will now study YAT(yet another technology) Linq to Xml. Most of the time I feel like I can't get there from here.

    Cheers,

    Lionel

    • Marked as answer by lionelthomas Saturday, May 14, 2011 4:40 PM
    Saturday, May 14, 2011 2:22 PM

All replies

  • Hi this happens because when you add a new row (object) in the dataset table then you loose the root element. So dataset adds a default root element. For example if you have person class with a property name "Name" then it would be serialized as

    <person>

         <name>Person1</name>

    </person>

    Now person is the root. When you add another person there is no root. So dataset  adds a root.

    The solution would be serialize a list of persons. So that you can add new persons to that list. As list can't be serialized by xml serializer you need to use a Contact serializer (To use contact serializer you may need to go to add reference menu and then select system.runtime.serialization and then use it with using System.Runtime.Serialization)

    Here is an example of using DataContract serialization and then manipulate it through Dataset.

      [DataContract(Name = "PersonList", Namespace = "Your Project Namespace")]
      public class PersonList
      {
        [DataMember]
        public IList<Person> persons = new List<Person>();
      }
    
      public class Person
      {
        public string Name { get; set; }
        public int Age { get; set; }
      }
    
    // the code for serialization, read and write with dataset and then deserialize
    
          //list object
          PersonList pl = new PersonList();
          pl.persons.Add(p);
    
          FileStream fs1 = new FileStream(Application.StartupPath + @"\test2.xml", FileMode.OpenOrCreate);
          DataContractSerializer ser = new DataContractSerializer(pl.GetType());
          ser.WriteObject(fs1, pl);
          fs1.Close();
    
          //read serialized xml
          DataSet ds1 = new DataSet();
          ds1.ReadXml(Application.StartupPath + @"\test2.xml");
    
          //add new data
          DataRow row1 = ds1.Tables["Person"].NewRow();
          row1["Name"] = "Person2";
          row1["Age"] = 30;
          row1.SetParentRow(ds1.Tables["persons"].Rows[0]);// set relationship to the list
          ds1.Tables["Person"].Rows.Add(row1);
          ds1.Tables["Person"].AcceptChanges();
    
          ds1.AcceptChanges();
          //write it back
          ds1.WriteXml(Application.StartupPath + @"\test3.xml");
          
          //deserialization
          FileStream fs2 = new FileStream(Application.StartupPath + @"\test3.xml", FileMode.Open);
          PersonList pl2 = (PersonList)ser.ReadObject(fs2);
          fs2.Close();
    
    Hope this helps

    Friday, May 13, 2011 6:15 PM
  • Thanks Albin for the reply.

    Not sure if I understand but in my case using your example Person is the root and I don't want to add other persons. What appears to be happening is that the schema that I inferred from my Person class is not naming Person as the root. When I read the xsd into the dataset and then read the xml everything is okay but when I write it out it has not recognized that person is the root from the xsd and adds a root NewDataSet.

    It would seem that the xsd that is created from inferschema has not specified the root correctly. Is there a way to do this?

    Here is my class:

        public class GameInit
        {
            public string name
            { get; set; }

            public string folder
            { get; set; }

            public string initFileName
            { get; set; }


            /// <summary>
            /// Constructs Initialization Object
            /// </summary>
            public GameInit()
            {
     
            }

            public GameInit DeserializeObject(string filename)
            {
                // Create an instance of the XmlSerializer specifying type and namespace.
                XmlSerializer serializer = new
                XmlSerializer(typeof(GameInit));

                // A FileStream is needed to read the XML document.
                FileStream fs = new FileStream(filename, FileMode.Open);
                XmlReader reader = XmlReader.Create(fs);

                // Declare an object variable of the type to be deserialized.
                GameInit init;

                // Use the Deserialize method to restore the object's state.
                init = (GameInit)serializer.Deserialize(reader);

                fs.Close();
                return init;

            }

            public void SerializeObject(string filename, GameInit init)
            {

                XmlSerializer serializer =
                    new XmlSerializer(typeof(ScreenInit));

                // Create an XmlTextWriter using a FileStream.
                Stream fs = new FileStream(filename, FileMode.Create);

                XmlWriterSettings settings = new XmlWriterSettings();
                settings.Indent = true;

                XmlWriter writer = XmlWriter.Create(fs, settings);

                // Serialize using the XmlTextWriter.
                serializer.Serialize(writer, init);
                writer.Close();
            }

            public void InferSchema(string path, string fileNameXml, string fileNameXsd )
            {
                //declare and instantiate a schema inferencer
                XmlSchemaInference infer = new XmlSchemaInference();
                //declare and instantiate a schema set to hold the inferenced schema
                XmlSchemaSet sc = null;
                sc = infer.InferSchema(XmlReader.Create(path + fileNameXml));
                XmlSchema[] schemas = new XmlSchema[sc.Count];
                sc.CopyTo(schemas, 0);
                XmlWriterSettings settings = new XmlWriterSettings();
                settings.Indent = true;
                XmlWriter w = XmlWriter.Create(new StreamWriter(path + fileNameXsd), settings);
                schemas[0].Write(w);
                w.Close();
            }
        }

    My xsd:

    <?xml version="1.0" encoding="utf-8"?>
    <xs:schema xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
               xmlns:xsd="http://www.w3.org/2001/XMLSchema"
               xmlns:xs="http://www.w3.org/2001/XMLSchema"
               attributeFormDefault="unqualified" elementFormDefault="qualified"
               >
      <xsd:element name="GameInit">
        <xsd:complexType>
          <xsd:sequence>
            <xsd:element name="name" type="xsd:string" />
            <xsd:element name="folder" type="xsd:string" />
            <xsd:element name="initFileName" type="xsd:string" />
          </xsd:sequence>
        </xsd:complexType>
      </xsd:element>
    </xs:schema>

    My xml:

    <?xml version="1.0" encoding="iso-8859-1"?>
      <GameInit>
        <name>GameDesign</name>
        <folder>GameScreens</folder>
        <initFileName>ScreenMainMenu.xml</initFileName>
      </GameInit>

    Friday, May 13, 2011 7:08 PM
  • Hi lionelthomas;

    When you use DataSet.WriteXml it uses the DataSet Name as the root node for the XML document. When no name is given to the Dataset then by default the value of NewDataSet is given to the root node. The same thing goes for the DataTable the DataTable name is used to as the parent node to each row of data. So for example if you have the following:

     

    DataSet ds = new DataSet("MyRootName");
    DataTable dt = new DataTable("MyTable1");
    DataColumn dc = new DataColumn("MyColumn1", typeof(Int32));
    dt.Columns.Add(dc);
    dc = new DataColumn("MyColumn2", typeof(string));
    dt.Columns.Add(dc);
    
    // Then fill the columns with data
    

     

     

    Then when you execute DataSet.WriteXml you will get the following XML document

     

    <?xml version="1.0" standalone="yes"?>
    <MyRootName>
     <MyTable1>
     <MyColumn1>1</Column1>
     <MyColumn2>Row Data 1</Column2>
     </MyTable1>
     <MyTable1>
     <MyColumn1>2</Column1>
     <MyColumn2>Row Data 2</Column2>
     </MyTable1>
     <MyTable1>
     <MyColumn1>3</Column1>
     <MyColumn2>Row Data 3</Column2>
     </MyTable1>
    </MyRootName>
    

     

     
    Hope that was of some help.

    Fernando

     


    If a post answers your question, please click "Mark As Answer" on that post and "Mark as Helpful".
    Saturday, May 14, 2011 2:48 AM
  • Hi Fernando,

    Thanks for the good explanation. However, my challenge is that when I read in the xsd to create the dataset, I don't know what the root name is. How does one specify the root name in the xsd and/or the xml? My application, an xml file editor, requires that I have to get all the specifics of the xml from the xsd and/or the xml.

    Also it appears that datasets are dated technology and I should use Linq to Xml. But I'm running into YAT(Yet Another Technology). And there is no assurance that I can do what I want in that technology. Ultimately, I want the xsd/xml file combination to be completely self-defining.

    Thanks,

    Lionel

    Saturday, May 14, 2011 12:27 PM
  • Hi Lionel;

    Sorry but I am no expert on XML or XSD and would not be able to help you with that. I guess I misunderstood the question.

    To get better results on XML and XSD question you should post the question in the, XML, System.Xml, MSXML and XmlLite Forum at http://social.msdn.microsoft.com/Forums/en-US/xmlandnetfx

    Fernando


    If a post answers your question, please click "Mark As Answer" on that post and "Mark as Helpful".
    Saturday, May 14, 2011 1:48 PM
  • Hi Fernando,

    I too am sorry you cannot answer my question. I had originally posted my question there but a moderator moved it.

    I will now study YAT(yet another technology) Linq to Xml. Most of the time I feel like I can't get there from here.

    Cheers,

    Lionel

    • Marked as answer by lionelthomas Saturday, May 14, 2011 4:40 PM
    Saturday, May 14, 2011 2:22 PM