I am trying to deserialize an XML document but the code I using is returning Null Value each time.
I have a XML like this
<?xml version="1.0" encoding="utf-8"?>
<RegistrationOpenData xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://example.gov">
<Description>Registration data is collected by ABC XYZ</Description>
<InformationURL>http://www.example.com/html/hpd/property-reg-unit.shtml</InformationURL>
<SourceAgency>ABC Department of Housing</SourceAgency>
<SourceSystem>PREMISYS</SourceSystem>
<StartDate>2016-02-29T00:03:06.642772-05:00</StartDate>
<EndDate i:nil="true" />
<Registrations>
<Registration xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<RegistrationID>108260</RegistrationID>
<BuildingID>4731</BuildingID>
</Registration>
</Registrations>
</RegistrationOpenData>
to deserialize it, I have created a class
using System.Xml.Serialization;
using System.Xml;
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.0.30319.1")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(Namespace="http://example.gov")]
[System.Xml.Serialization.XmlRootAttribute(Namespace="http://example.gov", IsNullable=true)]
public partial class Registration : InfoClass {
private long registrationIDField;
private bool registrationIDFieldSpecified;
private System.Nullable<long> buildingIDField;
private bool buildingIDFieldSpecified;
public long RegistrationID
{
get
{
return this.registrationIDField;
}
set
{
this.registrationIDField = value;
}
}
[System.Xml.Serialization.XmlIgnoreAttribute()]
public bool RegistrationIDSpecified {
get {
return this.registrationIDFieldSpecified;
}
set {
this.registrationIDFieldSpecified = value;
}
}
[System.Xml.Serialization.XmlElementAttribute(IsNullable=true)]
public System.Nullable<long> BuildingID {
get {
return this.buildingIDField;
}
set {
this.buildingIDField = value;
}
}
[System.Xml.Serialization.XmlIgnoreAttribute()]
public bool BuildingIDSpecified {
get {
return this.buildingIDFieldSpecified;
}
set {
this.buildingIDFieldSpecified = value;
}
}
and the code I am using is
public void Test()
{
Registration RegistrationVal = null;
var xRoot = new XmlRootAttribute();
xRoot.ElementName = "RegistrationOpenData";
xRoot.Namespace = "http://services.hpd.gov";
xRoot.IsNullable = true;
var serializer = new XmlSerializer(typeof(Registration), xRoot);
using (TextReader reader = new StreamReader(#"D:\sample.xml"))
{
RegistrationVal = (Registration)serializer.Deserialize(reader);
}
}
Here it is always returning Null value.
Thanks in advance for your help.
Your problem is in the xml because it has a list of registrations. If you remove <Registration> and <Registrations> tag then it works. Do you need the Registration and Registrations because in this case you have to work with Lists.
You could do it like in this example (Deserializing nested xml into C# objects)
And create a own class Registrations which hold a List of Registration Elements.
With this code it works. Create a super class:
[XmlRoot("RegistrationOpenData")]
public class RegistrationOpenData
{
[XmlElement("Registrations")]
public Registrations Regs { get; set; }
}
and the Registrations:
[XmlRoot("Registrations")]
public class Registrations
{
[XmlElement("Registration")]
public List<Registration> Regs { get; set; }
}
and the Registration should be the same as before.
The main function should change to this:
static void Main(string[] args)
{
RegistrationOpenData RegistrationVal = null;
var xRoot = new XmlRootAttribute();
xRoot.ElementName = "RegistrationOpenData";
xRoot.Namespace = "http://services.hpd.gov";
xRoot.IsNullable = true;
var serializer = new XmlSerializer(typeof(RegistrationOpenData), xRoot);
using (TextReader reader = new StreamReader(#"D:\sample.xml"))
{
RegistrationVal = (RegistrationOpenData)serializer.Deserialize(reader);
}
}
Related
I'm having problems serializing an object which has been added to my project via a Service Reference to XML.
The object which is referenced via the service reference has the structure:
public class GetProspectsContactStatusParametersV1
{
public GetProspectsContactStatusParametersV1()
{
Version = 1;
}
public int Version { get; set; }
public ProspectIds ProspectIDs { get; set; }
public InterestIds InterestIDs { get; set; }
public class ProspectIds
{
private List<int> _prospectIds = new List<int>();
[XmlElement("ProspectId")]
public List<int> Items
{
get { return _prospectIds; }
set { _prospectIds = value; }
}
}
public class InterestIds
{
private List<int> _interestIds = new List<int>();
[XmlElement("InterestId")]
public List<int> Items
{
get { return _interestIds; }
set { _interestIds = value; }
}
}
}
This code forms part of a Web Service project which I reference in another application. Using the reference in the other project I create an instance of the above object as follows:
var request = new ProspectsWebServiceMetadata.GetProspectsContactStatusParametersV1();
request.Version = 1;
request.InterestIDs = new ProspectsWebServiceMetadata.InterestIds
{
2,3,4,5
};
And I then try to Serialize this object to XML using a basic XmlSerializer:
public static string ToXmlString(object source)
{
using (StringWriter sww = new StringWriter())
using (XmlWriter writer = XmlWriter.Create(sww))
{
System.Xml.Serialization.XmlSerializer ser = new System.Xml.Serialization.XmlSerializer(source.GetType());
ser.Serialize(writer, source);
return sww.ToString();
}
}
The XML that gets created is as follows:
<?xml version="1.0" encoding="utf-16"?>
<GetProspectsContactStatusParametersV1 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Version>1</Version>
<InterestIDs>
<int>2</int>
<int>3</int>
<int>4</int>
<int>5</int>
</InterestIDs>
The part of the XML above within "InterestIDs" should have "InterestID" instead of "int".
The code generated as part of importing the reference seems to indicate that it should serialize correctly, but obviously it does not:
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.Runtime.Serialization", "4.0.0.0")]
[System.Runtime.Serialization.CollectionDataContractAttribute(Name="InterestIds", Namespace="http://www.testing.com/", ItemName="InterestId")]
[System.SerializableAttribute()]
public class InterestIds : System.Collections.Generic.List<int> {
}
Any ideas?
The attribute in the final snippet for the CollectionDataContractAttribute is actually marking the data for the DataContractSerializer, not the XmlSerializer.
I'm new to XMLdeserialization. I used xsd.exe to generate object classes for performing a deserialization on an existing XML file. When I run my solution below, I get the error
System.InvalidOperationException: < xmlns=''> was not expected
on the s = (NewDataSet)xs.Deserialize(sr) call. I looked this error up on Stack Overflow, and everyone says it's in the XMLRootAttribute line.
[System.Xml.Serialization.XmlRootAttribute(Namespace = "", IsNullable = false)]
How can I correct this line? Or where can I find some documentation that explains how to correct it?
Also, why doesn't xsd.exe generate the correct XmlRootAttribute line in the first place? Am I invoking this utility wrong? Or are there some situations the xsd.exe utility can't handle?
public class Program
{
static void Main(string[] args)
{
SortedSet<string> symbolsEstablished = new SortedSet<string>();
GetXmlDataSet("Expt 2buy.xml", ref symbolsEstablished);
}
public static void GetXmlDataSet(string fileName, ref SortedSet<string> symbols)
{
XmlSerializer xs = new XmlSerializer(typeof(NewDataSet));
StreamReader sr = new StreamReader(#"C:\Users\mehl\AppData\Roaming\Fidelity Investments\WealthLabPro\1.0.0.0\Data\DataSets\" + fileName);
NewDataSet s = (NewDataSet)xs.Deserialize(sr);
Console.WriteLine(s.Items[0].DSString);
sr.Close();
}
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "2.0.50727.3038")]
[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 DataSet
{
private string nameField;
private string scaleField;
private string barIntervalField;
private string dSStringField;
private string providerNameField;
[System.Xml.Serialization.XmlElementAttribute(Form = System.Xml.Schema.XmlSchemaForm.Unqualified)]
public string Name
{
get { return this.nameField; }
set { this.nameField = value; }
}
[System.Xml.Serialization.XmlElementAttribute(Form = System.Xml.Schema.XmlSchemaForm.Unqualified)]
public string Scale
{
get { return this.scaleField; }
set { this.scaleField = value; }
}
[System.Xml.Serialization.XmlElementAttribute(Form = System.Xml.Schema.XmlSchemaForm.Unqualified)]
public string BarInterval
{
get { return this.barIntervalField; }
set { this.barIntervalField = value; }
}
[System.Xml.Serialization.XmlElementAttribute(Form = System.Xml.Schema.XmlSchemaForm.Unqualified)]
public string DSString
{
get { return this.dSStringField; }
set { this.dSStringField = value; }
}
[System.Xml.Serialization.XmlElementAttribute(Form = System.Xml.Schema.XmlSchemaForm.Unqualified)]
public string ProviderName
{
get { return this.providerNameField; }
set { this.providerNameField = value; }
}
}
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "2.0.50727.3038")]
[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 NewDataSet
{
private DataSet[] itemsField;
[System.Xml.Serialization.XmlElementAttribute("DataSet")]
public DataSet[] Items
{
get { return this.itemsField; }
set { this.itemsField = value; }
}
}
}
The entire above code segment is wrapped in a screener2wl namespace.
And here's the XML file I'm trying to deserialize:
<?xml version="1.0"?>
<DataSet xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Name>Expt 2buy</Name>
<Scale>Daily</Scale>
<BarInterval>0</BarInterval>
<DSString>AAL,AFSI,BEN,BIG,BLKB,CDK,COHR,CRUS,EGP,EPE,ETH,FB,HUM,LSTR,MDP,MSI,NYT,TAST,TER,TSO,TXN,UTHR,VASC,VLO,WRI,</DSString>
<ProviderName>FidelityStaticProvider</ProviderName>
</DataSet>
Using xml linq :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication1
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
XDocument doc = XDocument.Load(FILENAME);
DataSet ds = doc.Descendants("DataSet").Select(x => new DataSet() {
nameField = (string)x.Element("Name"),
scaleField = (string)x.Element("Scale"),
barIntervalField = (string)x.Element("BarInterval"),
dSStringField = (string)x.Element("DSString"),
providerNameField = (string)x.Element("ProviderName")
}).FirstOrDefault();
}
}
public partial class DataSet
{
public string nameField { get; set; }
public string scaleField { get; set; }
public string barIntervalField { get; set; }
public string dSStringField { get; set; }
public string providerNameField { get; set; }
}
}
I got to thinking ... isn't it odd xsd.exe would provide a code generated solution that defines two independent XmlRootAttribute nodes? Can an XML file even have two Root Nodes? Maybe the solutions xsd.exe generates shouldn't be taken too literally. :-)
So after editing its solution, and removing one part with a second XmlRootAttribute defined, I got the solution below, which works.
namespace screener2wl
{
public class Program
{
static void Main(string[] args)
{
SortedSet<string> symbolsEstablished = new SortedSet<string>();
GetXmlDataSet("Expt 2buy.xml", ref symbolsEstablished);
}
public static void GetXmlDataSet(string fileName, ref SortedSet<string> symbols)
{
XmlSerializer xs = new XmlSerializer(typeof(DataSet));
StreamReader sr = new StreamReader(#"C:\Users\mehl\AppData\Roaming\Fidelity Investments\WealthLabPro\1.0.0.0\Data\DataSets\" + fileName);
DataSet s = (DataSet)xs.Deserialize(sr);
Console.WriteLine(s.DSString);
sr.Close();
}
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
[System.Xml.Serialization.XmlRootAttribute(IsNullable = false)]
public class DataSet
{
private string nameField;
private string scaleField;
private string barIntervalField;
private string dSStringField;
private string providerNameField;
[System.Xml.Serialization.XmlElementAttribute(Form = System.Xml.Schema.XmlSchemaForm.Unqualified)]
public string Name
{
get { return this.nameField; }
set { this.nameField = value; }
}
[System.Xml.Serialization.XmlElementAttribute(Form = System.Xml.Schema.XmlSchemaForm.Unqualified)]
public string Scale
{
get { return this.scaleField; }
set { this.scaleField = value; }
}
[System.Xml.Serialization.XmlElementAttribute(Form = System.Xml.Schema.XmlSchemaForm.Unqualified)]
public string BarInterval
{
get { return this.barIntervalField; }
set { this.barIntervalField = value; }
}
[System.Xml.Serialization.XmlElementAttribute(Form = System.Xml.Schema.XmlSchemaForm.Unqualified)]
public string DSString
{
get { return this.dSStringField; }
set { this.dSStringField = value; }
}
[System.Xml.Serialization.XmlElementAttribute(Form = System.Xml.Schema.XmlSchemaForm.Unqualified)]
public string ProviderName
{
get { return this.providerNameField; }
set { this.providerNameField = value; }
}
}
}
}
Bottom line, use the code solutions xsd.exe generates from your XML data file as a guide, not a truth. It's a great tool, but needs to be used with a grain of salt. ... welcome your comments on my XMLdeserialization problem.
I have an XML source that I can't change and I want to deserialise this using XmlSerializer.
I can do this fine however there are some arrays of custom classes that I would like to access the array by a String and not in Integer.
I know I can use
public ClassName this[string index]
but I can't work out where to add this to my Class.
I want to be able to call
Object.Transaction["TransactionTypeName"]
instead of
Object.Transaction[0]
This is a stripped down version of the class.
public partial class Configuration
{
private ConfigurationTransaction[] transactionsField;
[System.Xml.Serialization.XmlArrayItemAttribute("Transaction", IsNullable = false)]
public List<ConfigurationTransaction> Transactions
{
get
{
return this.transactionsField;
}
set
{
this.transactionsField = value;
}
}
}
public partial class ConfigurationTransaction
{
private string typeField;
[System.Xml.Serialization.XmlAttributeAttribute()]
public string type
{
get
{
return this.typeField;
}
set
{
this.typeField = value;
}
}
}
A simplified example code of your classes with indexer.
While we need to save the value to access the indexer will have to create additional class.
public class Configuration
{
public ConfigurationTransaction this[string transactionName]
{
get
{
return Transactions.First(tran => tran.TransactionName == transactionName).ConfigurationTransaction;
}
set
{
int index = Transactions.FindIndex(tran => tran.TransactionName == transactionName);
if (index >= 0)
Transactions[index] = new PairHelper { TransactionName = transactionName, ConfigurationTransaction = value };
else
Transactions.Add(new PairHelper { TransactionName = transactionName, ConfigurationTransaction = value });
}
}
[EditorBrowsable(EditorBrowsableState.Never)]
public List<PairHelper> Transactions { get; set; }
}
public class ConfigurationTransaction
{
[XmlAttribute()]
public string Type { get; set; }
}
public class PairHelper
{
public string TransactionName { get; set; }
public ConfigurationTransaction ConfigurationTransaction { get; set; }
}
It's work:
Configuration conf = new Configuration();
conf.Transactions = new List<PairHelper>();
conf["fooTran"] = new ConfigurationTransaction { Type = "foo" };
conf["barTran"] = new ConfigurationTransaction { Type = "bar" };
var xs = new XmlSerializer(typeof(Configuration));
using (var fs = new FileStream("test.txt", FileMode.Create))
{
xs.Serialize(fs, conf);
}
Configuration conf2;
using (var fs = new FileStream("test.txt", FileMode.Open))
{
conf2 = (Configuration)xs.Deserialize(fs);
}
foreach (var tran in conf2.Transactions)
Console.WriteLine(tran.TransactionName + " : " + tran.ConfigurationTransaction);
Console.WriteLine(conf2["fooTran"].Type);
Console.WriteLine(conf2["barTran"].Type);
XML will look like this:
<?xml version="1.0"?>
<Configuration xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Transactions>
<PairHelper>
<TransactionName>fooTran</TransactionName>
<ConfigurationTransaction Type="foo" />
</PairHelper>
<PairHelper>
<TransactionName>barTran</TransactionName>
<ConfigurationTransaction Type="bar" />
</PairHelper>
</Transactions>
</Configuration>
I was able to add in this into the Configuration class.
public ConfigurationTransaction this[String index]
{
get
{
foreach (var item in Transactions)
{
if (item.type.ToLower().Trim() == index.ToLower().Trim())
{
return item;
}
}
return null;
}
}
And call it like
Object["TransactionTypeName"]
I think that's what I did anyway, I ended up manually importing all the data into a SQL database and creating an Entity Framework class to access it and depricated the XML solution.
I don't know if the topic is correct, if not please correct. So far i am not sure what to search for my problem so maybe the question has already been answered before.
Currently i have the following class (as example):
[Serializable]
public class Sample
{
public string Something { get; set; }
public List<Parameter> Parameters { get; set; }
}
[Serializable]
public class Parameter
{
public string Name { get; set; }
public string Value { get; set; }
}
This structure i have to serialize to the following XML:
<Sample>
<Something>1234512345112345</Something>
<Parameters>
<Name>Value</Name>
<Name>Value</Name>
</Parameters>
</Sample>
So the XML should contain the property value of the attribute "Name" as XML-Element Name.
Update 20.05.2015
I have the following XML content:
<?xml version="1.0" encoding="utf-16" ?>
<ProcessData>
<ID>123456</ID>
<IDYTPE>BASEPLATE</IDYTPE>
<State>FAIL</State>
<Recipe>654321</Recipe>
<ProcessDataParameter>
<test_0>0</test_0>
<test_1>12,34</test_1>
<test_2>24,68</test_2>
<test_3>37,02</test_3>
<test_4>49,36</test_4>
<test_5>61,7</test_5>
</ProcessDataParameter>
</ProcessData>
When i try to use the following code to deserialize:
public void ReadXml(XmlReader reader)
{
reader.ReadStartElement("ProcessData");
this.Id = reader.ReadElementString("ID");
this.IdType = reader.ReadElementString("IDYTPE");
this.State = reader.ReadElementString("State");
this.Recipe = reader.ReadElementString("Recipe");
reader.ReadStartElement("ProcessDataParameter");
this.ProcessDataParameter = new List<ProcessDataParameter>();
var subTree = reader.ReadSubtree();
while (subTree.Read())
{
if (subTree.NodeType == XmlNodeType.Text)
{
var nm = subTree.LocalName;
//Parameters.Add(new Parameter { Name = nm, Value = subTree.Value });
}
}
reader.ReadEndElement();
}
Everything gets read out fine expect the process data parameters.
It seems like the subTree.Read() just reades the element out of the XML content instead of all elements contained in the .
In the while loop the reader goes through the following values (debuged)
test_0 (start tag)
0 (value between the tag)
test_0 (end tag
and then out of the while.
Seems like the reader sees the as an subtree.
Further only the 0 - value gets recognized as XmlNodeType.Text
You could implement IXmlSerializable and create your own custom serialization behaviour for your Sample class. So in your case something like this should work
[Serializable]
public class Sample : IXmlSerializable
{
public string Something { get; set; }
public List<Parameter> Parameters { get; set; }
public XmlSchema GetSchema()
{
return null;
}
public void ReadXml(XmlReader reader)
{
XmlDocument doc = new XmlDocument();
doc.Load(reader);
Something = doc.SelectSingleNode(#"/Sample/Something").FirstChild.Value;
var parameters = doc.SelectSingleNode(#"/Sample/Parameters");
if (parameters.HasChildNodes)
{
Parameters = new List<Parameter>();
foreach (XmlElement childNode in parameters.ChildNodes)
{
Parameters.Add(new Parameter {Name = childNode.LocalName, Value = childNode.FirstChild.Value});
}
}
}
public void WriteXml(XmlWriter writer)
{
writer.WriteElementString("Something", this.Something);
writer.WriteStartElement("Parameters");
foreach (var parameter in Parameters)
{
writer.WriteElementString(parameter.Name, parameter.Value);
}
writer.WriteEndElement();
}
}
Updated to include ReadXml implementation for deserialization
I'm not quite sure if the ReadXml is complete as I can't test this now, you might have to tweak it a bit for the Parameters
Try this
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Xml;
using System.Xml.Serialization;
namespace ConsoleApplication1
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
Sample sample = new Sample(){
Something = "1234512345112345",
Parameters = new List<Parameter>(){
new Parameter(){
Name = new List<string>(){"Value", "Value"}
}
}
};
XmlSerializer serializer = new XmlSerializer(typeof(Sample));
StreamWriter writer = new StreamWriter(FILENAME);
serializer.Serialize(writer, sample);
writer.Flush();
writer.Close();
writer.Dispose();
XmlSerializer xs = new XmlSerializer(typeof(Sample));
XmlTextReader reader = new XmlTextReader(FILENAME);
Sample newSample = (Sample)xs.Deserialize(reader);
}
}
[XmlRoot("Sample")]
public class Sample
{
[XmlElement("Something")]
public string Something { get; set; }
[XmlElement("Parameters")]
public List<Parameter> Parameters { get; set; }
}
[XmlRoot("Parameters")]
public class Parameter
{
[XmlElement("Name")]
public List<string> Name { get; set; }
}
}
I created classes from a DTD (over XSD and xsd.exe) for my C# project, so I could easily deserialize them into a model class in my code.
This is roughly how I do it:
XmlReaderSettings readerSettings = new XmlReaderSettings();
readerSettings.DtdProcessing = DtdProcessing.Parse;
XmlReader reader = XmlReader.Create(tipsfile.FullName, readerSettings);
XmlRootAttribute xRoot = new XmlRootAttribute();
xRoot.ElementName = "Tips";
xRoot.IsNullable = true;
XmlSerializer serializer = new XmlSerializer(typeof(Tips), xRoot);
Tips tips = (Tips)serializer.Deserialize(reader);
reader.Close();
But, upon inspection of tips, I see that it holds no values at all from the original XML file. Also, I tried setting a breakpoint on the set-Body of a property of Tips, and it is never reached, although I know for sure that it has a value in the original XML file.
Why is the file not correctly deserialized into the class? Is something missing in my code?
Edit: Here is the Tips.cs file, which was auto-generated from the XSD
using System.Xml.Serialization;
namespace MyNs.Model
{
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "2.0.50727.3038")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://tempuri.org/caravan_1")]
[System.Xml.Serialization.XmlRootAttribute(Namespace = "http://tempuri.org/caravan_1", IsNullable = false)]
public partial class Tips
{
private Chapter[] chapterField;
[System.Xml.Serialization.XmlElementAttribute("Chapter")]
public Chapter[] Chapter
{
get
{
return this.chapterField;
}
set
{
this.chapterField = value;
}
}
}
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "2.0.50727.3038")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://tempuri.org/caravan_1")]
[System.Xml.Serialization.XmlRootAttribute(Namespace = "http://tempuri.org/caravan_1", IsNullable = false)]
public partial class Chapter
{
private string headingField;
private CarType[] carTypesField;
private Section[] sectionField;
private string countryField;
private string languageField;
public string Heading
{
get
{
return this.headingField;
}
set
{
this.headingField = value;
}
}
[System.Xml.Serialization.XmlArrayItemAttribute("CarType", IsNullable = false)]
public CarType[] CarTypes
{
get
{
return this.carTypesField;
}
set
{
this.carTypesField = value;
}
}
[System.Xml.Serialization.XmlElementAttribute("Section")]
public Section[] Section
{
get
{
return this.sectionField;
}
set
{
this.sectionField = value;
}
}
[System.Xml.Serialization.XmlAttributeAttribute()]
public string Country
{
get
{
return this.countryField;
}
set
{
this.countryField = value;
}
}
[System.Xml.Serialization.XmlAttributeAttribute()]
public string Language
{
get
{
return this.languageField;
}
set
{
this.languageField = value;
}
}
}
[... and so on ...]
And a sample XML file:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE Tips SYSTEM "caravan_1.dtd">
<Tips>
<Chapter Country="dafghagt" Language="de">
<Heading>fgagasgargaergarg</Heading>
<Section id="1">
<Heading>afdhwr6u5taehtaqh5</Heading>
<SubSection id="1">
<Heading>46k46kw6jhadfgadfha</Heading>
<Table>
<Row id="1">
<Heading>sgjsfgjsgfh443q572q356</Heading>
<Items>
<Item car="motor1" id="1">
<BodyText color="red">130*</BodyText>
<Subscript>3</Subscript>
</Item>
</Items>
</Row>
</Table>
</SubSection>
</Section>
</Chapter>
</Tips>
StreamReader sw = new StreamReader(fileName, false);
XmlTextReader xmlw = new XmlTextReader(sw);
XmlSerializer writer = new XmlSerializer(
type,
GetOverrides(),
extraTypes,
null,
null);
object o = writer.Deserialize(xmlw);
As per my comment, get overrides is just a method that contains something similar to your xml root attribute, I can show you this too if necessary
EDIT:
an example of extra types
public Type[] GetTypes()
{
return new Type[] { typeof(Class1), typeof(Class2)};
}
EDIT2: get overrides returns (Note this is untested)
XmlAttributes attribs = new XmlAttributes();
//attribs.XmlRoot - can edit root here (instead of xmlrootattribute)
attribs.XmlElements.Add(myAttribute);
XmlAttributeOverrides myOverride = new XmlAttributeOverrides();
myOverride.Add(typeof(Tips), "Tips", attribs);
return myOverride
Your object may not be identical to the xml model. In that case, you need map the properties of your class to the xml fields. I am giving you a quick example I had in one of my projects which may give you bit more information.
namespace DatabaseModel
{
[Description("Represents the selected nodes in the Coverage pane")]
[Serializable()]
[XmlRootAttribute("XmlCoverage", Namespace = "GISManager", IsNullable = false)]
public class TXmlCoverage : IXmlPolygon
{
[XmlArray(ElementName = "sbets"), XmlArrayItem(ElementName = "sbet")]
public List SbetsSelected { get; set; }
[XmlArray(ElementName = "sdcs"), XmlArrayItem(ElementName = "sdc")]
public List SdcsSelected { get; set; }
[XmlElementAttribute(ElementName = "area")]
public Boolean IsAreaSelected { get; set; }
[XmlElementAttribute(ElementName = "fpath")]
public Boolean IsFlightPathSelected { get; set; }
[XmlElementAttribute(ElementName = "fpoly")]
public Boolean IsFlightPolySelected { get; set; }
[XmlElementAttribute(ElementName = "mpoly")]
public Boolean IsMinePolySelected { get; set; }
[XmlElementAttribute(ElementName = "bldg")]
public Boolean IsBuildingsSelected { get; set; }
[XmlElementAttribute(ElementName = "hgt")]
public Boolean IsHeightSelected { get; set; }
[XmlIgnore()]
public Boolean ArePolygonsSelected { get { return IsMinePolySelected && IsBuildingsSelected && IsHeightSelected; } }
public TXmlCoverage()
{
SbetsSelected = new List<String>();
SdcsSelected = new List<String>();
IsAreaSelected = false;
IsFlightPathSelected = false;
IsFlightPolySelected = false;
}
}
}
So it turns out the problem is namespaces. Because my XML has no root namespace:
<Tips>
but the definition of my Model contained one:
[System.Xml.Serialization.XmlRootAttribute(Namespace = "http://tempuri.org/caravan_1", IsNullable = false)]
the Serializer didn't match any elements together. When removing the namespace attribute, it worked fine.
So now, I reworked the complete model and excluded any attributes that were not absolutely necessary (as it turns out, all but one were), so now every Property has just one Attribute: XmlElement and consorts.
using System.Xml.Serialization;
namespace MyNs.Model
{
[XmlRoot("Tips")]
public partial class Tips
{
[XmlElement("Chapter")]
public Chapter[] Chapter { get; set; }
}
[XmlRoot("Chapter")]
public partial class Chapter
{
[XmlElement("Heading")]
public string Heading { get; set; }
[XmlElement("CarType")]
public CarType[] CarTypes { get; set; }
[XmlElement("Section")]
public Section[] Section { get; set; }
[XmlAttribute("Country")]
public string Country { get; set; }
[XmlAttribute("Language")]
public string Language { get; set; }
}
[... and so on ...]
With a simple deserialization it works just fine now:
XmlReaderSettings readerSettings = new XmlReaderSettings { DtdProcessing = DtdProcessing.Parse };
XmlSerializer serializer = new XmlSerializer(typeof(Tips));
using (XmlReader reader = XmlReader.Create(fromXmlFile.FullName, readerSettings))
{
Tips tips = (Tips)serializer.Deserialize(reader);
return tips;
}