XML Serialization and Deserialization in C#
<job id="ID00004" name="PeakValCalcO">
<uses file="Seismogram_FFI_0_1_ID00003.grm" link="input" />
<uses file="PeakVals_FFI_0_1_ID00003.bsa" link="output" />
</job>
<job id="ID00005" name="SeismogramSynthesis" >
<uses file="FFI_0_1_txt.variation-s07930-h00000" link="input" />
<uses file="Seismogram_FFI_0_1_ID00005.grm" link="output" />
</job>
Let say I have this XML I want to convert into .net Object how can do this i tried it but it doesn't work correct...
public class jobs : List<job> { }
public class job
{
public string id { get; set; }
public string name { get; set; }
public List<uses> Files { get; set; }
}
public class uses
{
public string file { get; set; }
public string link { get; set; }
}
private void Form1_Load(object sender, EventArgs e)
{
XmlSerializer serializer = new XmlSerializer(typeof(jobs));
开发者_开发问答 TextReader tr = new StreamReader("CyberShake_100.xml");
job b = (job)serializer.Deserialize(tr);
tr.Close();
}
Hmm, there are several things wrong here:
1) Your xml document has no root element
It needs to look more like this:
<jobs>
<job id="ID00004" name="PeakValCalcO">
<uses file="Seismogram_FFI_0_1_ID00003.grm" link="input" />
<uses file="PeakVals_FFI_0_1_ID00003.bsa" link="output" />
</job>
<job id="ID00005" name="SeismogramSynthesis" >
<uses file="FFI_0_1_txt.variation-s07930-h00000" link="input" />
<uses file="Seismogram_FFI_0_1_ID00005.grm" link="output" />
</job>
</jobs>
2) You need some xml serialisation attributes
Attributes are used to tell the .Net framework how to serialise and deserialise xml. Without these the .Net frameowork is just guessing at your xml format, and so won't do a very good job. In this case you need:
- An
XmlRoot
attribute on yourjobs
class to tell the .Net framework what your root element type is - Some
XmlAttribute
attributes to indicate which properties are serialised as attributes - A
XmlElement
attribute to indicate that your array is serialised as a "flat" sequence of elements rather than as a nested array (and what those elements are called).
Combine all of this and your classes should look like this:
[XmlRoot("jobs")]
public class jobs : List<job> { }
public class job
{
[XmlAttribute]
public string id { get; set; }
[XmlAttribute]
public string name { get; set; }
[XmlElement("uses")]
public List<uses> Files { get; set; }
}
public class uses
{
[XmlAttribute]
public string file { get; set; }
[XmlAttribute]
public string link { get; set; }
}
For complex xml document this tends to get a bit tedious - there is a tool XSD.exe
that will automate all of this for you.
3) You are casting to the wrong type
Even if the serialisation succeeds you will get an InvalidCastExcpetion
trying to cast a jobs
instance to job
. Try this instead:
using (TextReader tr = new StreamReader("CyberShake_100.xml"))
{
jobs b = (jobs)serializer.Deserialize(tr);
}
You need to understand that id
and name
on <jobs>
are XML attributes - you need to express that in your classes, too:
public class job
{
[XmlAttribute]
public string id { get; set; }
[XmlAttribute]
public string name { get; set; }
public List<uses> Files { get; set; }
}
The same applies to your <uses>
tag and its class representation.
Also: a valid XML document always has one root element and one root only - your XML fragment is not a valid XML document.
You can use the XSD.exe tool to generate a class structure that matches your XML. It is probably the easiest way to have a working serialization object hierarchy.
At least you need the [XmlAttribute]
on id, name, file and link members.
You also cast to the wrong type, should be jobs b = (jobs)serializer.Deserialize(tr);
This is not a valid XML document, since it has more than a single root. That's the reason you can't use something out-of-the-box from the framework.
精彩评论