471,056 Members | 1,721 Online
Bytes | Software Development & Data Engineering Community
Post +

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 471,056 software developers and data experts.

XmlSerializer Collection with Collections

Hello I got this working but it is not how I really want it, basically
I have an xml file which has a root of <test> and can be filled with 3
different types of <question> elements with different attributes, all
share a base set of 4, one of the question types can have children
with <option> elements, this is how the xml looks after
serialization....

If you notice there is an extra <SelectionList> around the <option>'s
in the
final <question>, how can I write my class so I don't have this extra
<SelectionList> element....my class follows, you can see in the 2nd
public Question constructor is where I add the OptionList type....any
ideas, I know that really there is nothing wrong with having an extra
<SelectionList> element around the <option> elements but I really want
to know if my class is properly constucted.
<?xml version="1.0" encoding="utf-8"?>
<Test xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Question text="What is love?" type="Input" score="3"
mandatory="false" multiLine="false" maxlength="0" minlength="0"
validate="None" />
<Question text="This is better than sliced bread?" type="Input"
score="9" mandatory="false" multiLine="false" maxlength="0"
minlength="0" validate="None" />
<Question text="input question" type="Input" score="8"
mandatory="true" multiLine="true" maxlength="7" minlength="1"
initialvalue="hello" validate="Currency" answer="this is the answer"
/>
<Question text="What is square root of 2?" type="selection"
score="3" mandatory="false" multiLine="false" maxlength="0"
minlength="0" validate="None">
<SelectionList>
<Option text="first" selected="true" tooltip="hovertext"
answer="false" />
<Option text="second" selected="true" tooltip="hovertext"
answer="true" />
</SelectionList>
</Question>
</Test>

using System;
using System.Collections;
using System.IO;
using System.Xml;
using System.Xml.Serialization;

namespace TestCreator
{
public class TestSerializer
{
public TestSerializer()
{
//
// TODO: Add constructor logic here
//
}

//test class which will be serialized
[XmlRoot("Test")]
public class QuestionList
{
private ArrayList listQuestions;

public QuestionList()
{
listQuestions = new ArrayList();
}

[XmlElement("Question")]
public Question[] Questions
{
get
{
Question[] questions = new Question[ listQuestions.Count ];
listQuestions.CopyTo( questions );
return questions;
}
set
{
if( value == null ) return;
Question[] questions = (Question[])value;
listQuestions.Clear();
foreach( Question question in questions )
listQuestions.Add( question );
}
}

public int AddQuestion( Question question )
{
return listQuestions.Add( question );
}
}

public class OptionList
{
private ArrayList listOptions;

public OptionList()
{
listOptions = new ArrayList();
}
[XmlElement("Option")]
public Option[] Options
{
get
{
Option[] options = new Option[ listOptions.Count ];
listOptions.CopyTo( options );
return options;
}
set
{
if( value == null ) return;
Option[] options = (Option[])value;
listOptions.Clear();
foreach( Option option in options )
listOptions.Add( option );
}
}
public int AddOption( Option option )
{
return listOptions.Add( option );
}
}

public class Question
{
[XmlAttribute("text")] public string questionText;
[XmlAttribute("type")] public string type;
[XmlAttribute("score")] public int score;
[XmlAttribute("mandatory")] public bool mandatory;
[XmlAttribute("multiLine")] public bool multiline;
[XmlAttribute("maxlength")] public int maxlength;
[XmlAttribute("minlength")] public int minlength;
[XmlAttribute("initialvalue")] public string initialvalue;
[XmlAttribute("validate")] public Validation validate;
[XmlAttribute("answer")] public string answer;
[XmlElement("SelectionList")] public OptionList optionlist;
//[XmlElement("go")] public ArrayList optionlist;

public enum Validation
{
None,
Date,
Integer,
Currency
}
public Question()
{
}

public Question( string QuestionText, string Type, int Score, bool
Mandatory, OptionList opl )
{
questionText = QuestionText;
type = Type;
score = Score;
mandatory = Mandatory;
optionlist = opl;
}

public Question( string QuestionText, string Type, int Score, bool
Mandatory, bool MultiLine, int MaxLength, int MinLength, string
InitialValue, Validation Validate, string Answer)
{
questionText = QuestionText;
type = Type;
score = Score;
mandatory = Mandatory;
multiline = MultiLine;
maxlength = MaxLength;
minlength = MinLength;
initialvalue = InitialValue;
validate = Validate;
answer = Answer;
}
}

public class Option
{
[XmlAttribute("text")] public string label;
[XmlAttribute("selected")] public bool selected;
[XmlAttribute("tooltip")] public string tooltip;
[XmlAttribute("answer")] public bool answer;

public Option()
{
}

public Option( string Label, bool Selected, string Tooltip, bool
Answer )
{
label = Label;
selected = Selected;
tooltip = Tooltip;
answer = Answer;
}
}

public static void Serialize(QuestionList myList)
{
XmlSerializer s = new XmlSerializer( typeof( QuestionList ) );
TextWriter w = new StreamWriter( @"c:\list.xml" );
s.Serialize( w, myList );
w.Close();
}
}
}

To test do this:
TestSerializer.QuestionList myList = new
TestSerializer.QuestionList();
myList.AddQuestion( new TestSerializer.Question("What is
love?","Input",3,false ) );

TestSerializer.OptionList opl = new TestSerializer.OptionList();
opl.AddOption( new TestSerializer.Option("first",true,"hovertext",fal se));
opl.AddOption( new TestSerializer.Option("second",true,"hovertext",tr ue));
myList.AddQuestion( new TestSerializer.Question("What is the square
root of 2?","selection",3,false,opl ) );
TestSerializer.Serialize(myList);
Nov 12 '05 #1
3 4054
> I really want
to know if my class is properly constucted.
your class is fine.

But it is possible to shape the XML differently. For example, if you change
from this:
[XmlElement("SelectionList")] public OptionList optionlist;

to this:
[XmlElement("Option", typeof(Option))]
public ArrayList options;

you will get this:
<Test>
<Question .../>
<Question ...>
<Option .../>
<Option .../>
</Question>
</Test>

But you will lose the type-enforcement provided by OptionList. Another
way to do it is to embed the Option[] in the Question type directly,
instead of going through the intermediary type OptionList. So, move the
following snippet from OptionList directly into Question:

--- begin snip ----
private ArrayList listOptions= new ArrayList();

[XmlElement("Option")]
public Option[] Options
{
get {..}
set {...}
}
public int AddOption( Option option )
{
return listOptions.Add( option );
}
--- end snip ----

This retains the type enforcement you have now, and will get you the simpler
XML you described. In fact this approach seems more parallel with your
existing design for QuestionList. Put aside the names for a moment and
think about it. Instead of QuestionList, let's call it QuestionSet. In
the current design,

- a bunch of Question objects are contained within a QuestionSet
- a bunch of Option objects are contained within an OptionList
- a single OptionList object is contained within a Question

Whereas in the modified version,

- a bunch of Question objects are contained within a QuestionSet
- a bunch of Option objects are contained within a Question.

It is the extra level of object containment in the original version that
gets you the extra level of XML hierarchy.
-Dino
"MattB" <MB*********@yahoo.co.uk> wrote in message
news:b4*************************@posting.google.co m... Hello I got this working but it is not how I really want it, basically
I have an xml file which has a root of <test> and can be filled with 3
different types of <question> elements with different attributes, all
share a base set of 4, one of the question types can have children
with <option> elements, this is how the xml looks after
serialization....

If you notice there is an extra <SelectionList> around the <option>'s
in the
final <question>, how can I write my class so I don't have this extra
<SelectionList> element....my class follows, you can see in the 2nd
public Question constructor is where I add the OptionList type....any
ideas, I know that really there is nothing wrong with having an extra
<SelectionList> element around the <option> elements but I really want
to know if my class is properly constucted.
<?xml version="1.0" encoding="utf-8"?>
<Test xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Question text="What is love?" type="Input" score="3"
mandatory="false" multiLine="false" maxlength="0" minlength="0"
validate="None" />
<Question text="This is better than sliced bread?" type="Input"
score="9" mandatory="false" multiLine="false" maxlength="0"
minlength="0" validate="None" />
<Question text="input question" type="Input" score="8"
mandatory="true" multiLine="true" maxlength="7" minlength="1"
initialvalue="hello" validate="Currency" answer="this is the answer"
/>
<Question text="What is square root of 2?" type="selection"
score="3" mandatory="false" multiLine="false" maxlength="0"
minlength="0" validate="None">
<SelectionList>
<Option text="first" selected="true" tooltip="hovertext"
answer="false" />
<Option text="second" selected="true" tooltip="hovertext"
answer="true" />
</SelectionList>
</Question>
</Test>

using System;
using System.Collections;
using System.IO;
using System.Xml;
using System.Xml.Serialization;

namespace TestCreator
{
public class TestSerializer
{
public TestSerializer()
{
//
// TODO: Add constructor logic here
//
}

//test class which will be serialized
[XmlRoot("Test")]
public class QuestionList
{
private ArrayList listQuestions;

public QuestionList()
{
listQuestions = new ArrayList();
}

[XmlElement("Question")]
public Question[] Questions
{
get
{
Question[] questions = new Question[ listQuestions.Count ];
listQuestions.CopyTo( questions );
return questions;
}
set
{
if( value == null ) return;
Question[] questions = (Question[])value;
listQuestions.Clear();
foreach( Question question in questions )
listQuestions.Add( question );
}
}

public int AddQuestion( Question question )
{
return listQuestions.Add( question );
}
}

public class OptionList
{
private ArrayList listOptions;

public OptionList()
{
listOptions = new ArrayList();
}
[XmlElement("Option")]
public Option[] Options
{
get
{
Option[] options = new Option[ listOptions.Count ];
listOptions.CopyTo( options );
return options;
}
set
{
if( value == null ) return;
Option[] options = (Option[])value;
listOptions.Clear();
foreach( Option option in options )
listOptions.Add( option );
}
}
public int AddOption( Option option )
{
return listOptions.Add( option );
}
}

public class Question
{
[XmlAttribute("text")] public string questionText;
[XmlAttribute("type")] public string type;
[XmlAttribute("score")] public int score;
[XmlAttribute("mandatory")] public bool mandatory;
[XmlAttribute("multiLine")] public bool multiline;
[XmlAttribute("maxlength")] public int maxlength;
[XmlAttribute("minlength")] public int minlength;
[XmlAttribute("initialvalue")] public string initialvalue;
[XmlAttribute("validate")] public Validation validate;
[XmlAttribute("answer")] public string answer;
[XmlElement("SelectionList")] public OptionList optionlist;
//[XmlElement("go")] public ArrayList optionlist;

public enum Validation
{
None,
Date,
Integer,
Currency
}
public Question()
{
}

public Question( string QuestionText, string Type, int Score, bool
Mandatory, OptionList opl )
{
questionText = QuestionText;
type = Type;
score = Score;
mandatory = Mandatory;
optionlist = opl;
}

public Question( string QuestionText, string Type, int Score, bool
Mandatory, bool MultiLine, int MaxLength, int MinLength, string
InitialValue, Validation Validate, string Answer)
{
questionText = QuestionText;
type = Type;
score = Score;
mandatory = Mandatory;
multiline = MultiLine;
maxlength = MaxLength;
minlength = MinLength;
initialvalue = InitialValue;
validate = Validate;
answer = Answer;
}
}

public class Option
{
[XmlAttribute("text")] public string label;
[XmlAttribute("selected")] public bool selected;
[XmlAttribute("tooltip")] public string tooltip;
[XmlAttribute("answer")] public bool answer;

public Option()
{
}

public Option( string Label, bool Selected, string Tooltip, bool
Answer )
{
label = Label;
selected = Selected;
tooltip = Tooltip;
answer = Answer;
}
}

public static void Serialize(QuestionList myList)
{
XmlSerializer s = new XmlSerializer( typeof( QuestionList ) );
TextWriter w = new StreamWriter( @"c:\list.xml" );
s.Serialize( w, myList );
w.Close();
}
}
}

To test do this:
TestSerializer.QuestionList myList = new
TestSerializer.QuestionList();
myList.AddQuestion( new TestSerializer.Question("What is
love?","Input",3,false ) );

TestSerializer.OptionList opl = new TestSerializer.OptionList();
opl.AddOption( new TestSerializer.Option("first",true,"hovertext",fal se));
opl.AddOption( new TestSerializer.Option("second",true,"hovertext",tr ue));
myList.AddQuestion( new TestSerializer.Question("What is the square
root of 2?","selection",3,false,opl ) );
TestSerializer.Serialize(myList);

Nov 12 '05 #2
Hi thanks for the reply,

As you said the first method did work but as you mentioned I lost
type-enforcement provided by OptionList, my calling code changed to
this...

<code>
QuestionList myList = new QuestionList();

myList.AddQuestion( new Serialize.Question("This is better than sliced
bread?","Input",9,false ) );

myList.AddQuestion( new Serialize.Question("input question","input",
8, true, true, 7, 1, "hello", Serialize.Question.Validation.Currency,
"this is the answer"));

ArrayList arl = new ArrayList();
arl.Add( new Serialize.Option("first",true,"hovertext",false) );
arl.Add( new Serialize.Option("second",true,"hovertext",true) );

myList.AddQuestion( new Serialize.Question("What is slayer of
conformity?","selection",3,false, arl ) );

Serialize.WriteXml(myList);
</code>

I then tried your 2nd solution and the calling code above still worked
but I also noticed I could add Options without them being part or
under
a Question....

Option o1 = new Option("first",true,"hovertext",false);
myList.AddOption(o1);
Option o2 = new Option("second",true,"hovertext",true);
myList.AddOption(o2);

The xml looking something like this....top node fragment is still
filling and adding an arraylist to the question, bottom nodes are
added with the AddOption
command.

<Question text="What is slayer of conformity?" type="selection"
score="3" mandatory="false" multiLine="false" maxlength="0"
minlength="0" validate="None">
<Option text="first" selected="true" tooltip="hovertext"
answer="false" />
<Option text="second" selected="true" tooltip="hovertext"
answer="true" />
</Question>
<Option text="first" selected="true" tooltip="hovertext"
answer="false" />
<Option text="second" selected="true" tooltip="hovertext"
answer="true" />

Might there be a way to use addoption to add it to the current
question??

Perhaps I must fiddle with the methods, getter & setters, but I want
to know if you have any ideas or am I going in the right direction
here.

Thanks,
Matt

p.s. is .net version 2 changing xml serialization?

"Dino Chiesa [Microsoft]" <di****@online.microsoft.com> wrote in message news:<eK**************@TK2MSFTNGP09.phx.gbl>...
I really want
to know if my class is properly constucted.


your class is fine.

But it is possible to shape the XML differently. For example, if you change
from this:
[XmlElement("SelectionList")] public OptionList optionlist;

to this:
[XmlElement("Option", typeof(Option))]
public ArrayList options;

you will get this:
<Test>
<Question .../>
<Question ...>
<Option .../>
<Option .../>
</Question>
</Test>

But you will lose the type-enforcement provided by OptionList. Another
way to do it is to embed the Option[] in the Question type directly,
instead of going through the intermediary type OptionList. So, move the
following snippet from OptionList directly into Question:

--- begin snip ----
private ArrayList listOptions= new ArrayList();

[XmlElement("Option")]
public Option[] Options
{
get {..}
set {...}
}
public int AddOption( Option option )
{
return listOptions.Add( option );
}
--- end snip ----

This retains the type enforcement you have now, and will get you the simpler
XML you described. In fact this approach seems more parallel with your
existing design for QuestionList. Put aside the names for a moment and
think about it. Instead of QuestionList, let's call it QuestionSet. In
the current design,

- a bunch of Question objects are contained within a QuestionSet
- a bunch of Option objects are contained within an OptionList
- a single OptionList object is contained within a Question

Whereas in the modified version,

- a bunch of Question objects are contained within a QuestionSet
- a bunch of Option objects are contained within a Question.

It is the extra level of object containment in the original version that
gets you the extra level of XML hierarchy.
-Dino
"MattB" <MB*********@yahoo.co.uk> wrote in message
news:b4*************************@posting.google.co m...
Hello I got this working but it is not how I really want it, basically
I have an xml file which has a root of <test> and can be filled with 3
different types of <question> elements with different attributes, all
share a base set of 4, one of the question types can have children
with <option> elements, this is how the xml looks after
serialization....

If you notice there is an extra <SelectionList> around the <option>'s
in the
final <question>, how can I write my class so I don't have this extra
<SelectionList> element....my class follows, you can see in the 2nd
public Question constructor is where I add the OptionList type....any
ideas, I know that really there is nothing wrong with having an extra
<SelectionList> element around the <option> elements but I really want
to know if my class is properly constucted.
<?xml version="1.0" encoding="utf-8"?>
<Test xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Question text="What is love?" type="Input" score="3"
mandatory="false" multiLine="false" maxlength="0" minlength="0"
validate="None" />
<Question text="This is better than sliced bread?" type="Input"
score="9" mandatory="false" multiLine="false" maxlength="0"
minlength="0" validate="None" />
<Question text="input question" type="Input" score="8"
mandatory="true" multiLine="true" maxlength="7" minlength="1"
initialvalue="hello" validate="Currency" answer="this is the answer"
/>
<Question text="What is square root of 2?" type="selection"
score="3" mandatory="false" multiLine="false" maxlength="0"
minlength="0" validate="None">
<SelectionList>
<Option text="first" selected="true" tooltip="hovertext"
answer="false" />
<Option text="second" selected="true" tooltip="hovertext"
answer="true" />
</SelectionList>
</Question>
</Test>

using System;
using System.Collections;
using System.IO;
using System.Xml;
using System.Xml.Serialization;

namespace TestCreator
{
public class TestSerializer
{
public TestSerializer()
{
//
// TODO: Add constructor logic here
//
}

//test class which will be serialized
[XmlRoot("Test")]
public class QuestionList
{
private ArrayList listQuestions;

public QuestionList()
{
listQuestions = new ArrayList();
}

[XmlElement("Question")]
public Question[] Questions
{
get
{
Question[] questions = new Question[ listQuestions.Count ];
listQuestions.CopyTo( questions );
return questions;
}
set
{
if( value == null ) return;
Question[] questions = (Question[])value;
listQuestions.Clear();
foreach( Question question in questions )
listQuestions.Add( question );
}
}

public int AddQuestion( Question question )
{
return listQuestions.Add( question );
}
}

public class OptionList
{
private ArrayList listOptions;

public OptionList()
{
listOptions = new ArrayList();
}
[XmlElement("Option")]
public Option[] Options
{
get
{
Option[] options = new Option[ listOptions.Count ];
listOptions.CopyTo( options );
return options;
}
set
{
if( value == null ) return;
Option[] options = (Option[])value;
listOptions.Clear();
foreach( Option option in options )
listOptions.Add( option );
}
}
public int AddOption( Option option )
{
return listOptions.Add( option );
}
}

public class Question
{
[XmlAttribute("text")] public string questionText;
[XmlAttribute("type")] public string type;
[XmlAttribute("score")] public int score;
[XmlAttribute("mandatory")] public bool mandatory;
[XmlAttribute("multiLine")] public bool multiline;
[XmlAttribute("maxlength")] public int maxlength;
[XmlAttribute("minlength")] public int minlength;
[XmlAttribute("initialvalue")] public string initialvalue;
[XmlAttribute("validate")] public Validation validate;
[XmlAttribute("answer")] public string answer;
[XmlElement("SelectionList")] public OptionList optionlist;
//[XmlElement("go")] public ArrayList optionlist;

public enum Validation
{
None,
Date,
Integer,
Currency
}
public Question()
{
}

public Question( string QuestionText, string Type, int Score, bool
Mandatory, OptionList opl )
{
questionText = QuestionText;
type = Type;
score = Score;
mandatory = Mandatory;
optionlist = opl;
}

public Question( string QuestionText, string Type, int Score, bool
Mandatory, bool MultiLine, int MaxLength, int MinLength, string
InitialValue, Validation Validate, string Answer)
{
questionText = QuestionText;
type = Type;
score = Score;
mandatory = Mandatory;
multiline = MultiLine;
maxlength = MaxLength;
minlength = MinLength;
initialvalue = InitialValue;
validate = Validate;
answer = Answer;
}
}

public class Option
{
[XmlAttribute("text")] public string label;
[XmlAttribute("selected")] public bool selected;
[XmlAttribute("tooltip")] public string tooltip;
[XmlAttribute("answer")] public bool answer;

public Option()
{
}

public Option( string Label, bool Selected, string Tooltip, bool
Answer )
{
label = Label;
selected = Selected;
tooltip = Tooltip;
answer = Answer;
}
}

public static void Serialize(QuestionList myList)
{
XmlSerializer s = new XmlSerializer( typeof( QuestionList ) );
TextWriter w = new StreamWriter( @"c:\list.xml" );
s.Serialize( w, myList );
w.Close();
}
}
}

To test do this:
TestSerializer.QuestionList myList = new
TestSerializer.QuestionList();
myList.AddQuestion( new TestSerializer.Question("What is
love?","Input",3,false ) );

TestSerializer.OptionList opl = new TestSerializer.OptionList();
opl.AddOption( new TestSerializer.Option("first",true,"hovertext",fal se));
opl.AddOption( new TestSerializer.Option("second",true,"hovertext",tr ue));
myList.AddQuestion( new TestSerializer.Question("What is the square
root of 2?","selection",3,false,opl ) );
TestSerializer.Serialize(myList);

Nov 12 '05 #3
last things first. . .
p.s. is .net version 2 changing xml serialization? yes. Well, yes and no. Existing apps will continue to work as is,
unchanged.
But there is a new XML serialization model being introduced.


I then tried your 2nd solution and the calling code above still worked
but I also noticed I could add Options without them being part or
under
a Question....

Option o1 = new Option("first",true,"hovertext",false);
myList.AddOption(o1);
Option o2 = new Option("second",true,"hovertext",true);
myList.AddOption(o2);

Gee, that seems wrong. Why is there an AddOption() method on the
QuestionList type?
You should remove it if you don't want to add Options directly to the
QuestionList(). I imagine a QuestionList type like so:

public class QuestionList
{
private ArrayList listQuestions = new ArrayList();

[XmlElement("Question")]
public Question[] Questions
{
get {..}
set {..}
}
public int AddQuestion( Question question )
{
return listQuestions.Add( question );
}
}
Might there be a way to use addoption to add it to the current
question??

Sure! You would have to define QuestionList to have some idea of the
current question. then add a Method in QuestionList like so:

public int AddOption( Option option )
{
return currentQuestion.AddOption( option );
}

Then you could do myList.AddOption(...);

But maybe better (clearer for the user of this thing) would be to just
expose the currentQuestion property as a public property. So you would
get:

myList.Current.AddOption(...);

Perhaps I must fiddle with the methods, getter & setters, but I want
to know if you have any ideas or am I going in the right direction
here.


-Dino
Nov 12 '05 #4

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

8 posts views Thread by Harris Boyce | last post: by
3 posts views Thread by Anthony Bouch | last post: by
2 posts views Thread by magister | last post: by
2 posts views Thread by Kent Boogaart | last post: by
3 posts views Thread by Loui Mercieca | last post: by
2 posts views Thread by =?Utf-8?B?U2hhd24=?= | last post: by

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.