I'm trying simply to deserialize a xml file into a class.
This is my xml file:
<DirectoryListener inputDirectory="C:\test\"
outputDirectory="C:\keyValueXml\"
fileExt=".xml"/>
And this is my class (generated by "Paste Special"):
public class DirectoryListenConfig
{
[System.SerializableAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
[System.Xml.Serialization.XmlRootAttribute(Namespace = "", IsNullable = false)]
public partial class DirectoryListener
{
private string inputDirectoryField;
private string outputDirectoryField;
private string fileExtField;
[System.Xml.Serialization.XmlAttributeAttribute()]
public string inputDirectory
{
get
{
return this.inputDirectoryField;
}
set
{
this.inputDirectoryField = value;
}
}
[System.Xml.Serialization.XmlAttributeAttribute()]
public string outputDirectory
{
get
{
return this.outputDirectoryField;
}
set
{
this.outputDirectoryField = value;
}
}
[System.Xml.Serialization.XmlAttributeAttribute()]
public string fileExt
{
get
{
return this.fileExtField;
}
set
{
this.fileExtField = value;
}
}
}
}
And I tried to deserialize the xml file:
string path = "DirectoryConfig.xml";
XmlSerializer serializer = new XmlSerializer(typeof(DirectoryListener));
StreamReader reader = new StreamReader(path);
directoryConfig = (DirectoryListener)serializer.Deserialize(reader);//Throw an exception
And got an exception
An unhandled exception of type 'System.InvalidOperationException' occurred in System.Xml.dll Additional information: There is an error in XML document (2, 2).).
What is the problem? :\
Thanks!
Try this
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Serialization;
using System.IO;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
string path = #"c:\temp\test.xml";
XmlSerializer serializer = new XmlSerializer(typeof(DirectoryListener));
StreamReader reader = new StreamReader(path);
DirectoryListener directoryListener = (DirectoryListener)serializer.Deserialize(reader);//Throw an exception
}
}
[XmlRoot("DirectoryListener")]
public partial class DirectoryListener
{
private string inputDirectoryField;
private string outputDirectoryField;
private string fileExtField;
[XmlAttribute("inputDirectory")]
public string inputDirectory {get; set; }
[XmlAttribute("outputDirectory")]
public string outputDirectory { get; set; }
[XmlAttribute("fileExt")]
public string fileExt { get; set; }
}
}
Related
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 am trying to read a xml file and deserialize it to my InsertSensorType class and than read VALUE1,VALUE2 .. .I tried to add XmlElement name to my InsertionMetadata attribute in InsertSensorTypeMetadata class, but it doesn't work.I have searched and found solutions but they were not valid for this problem. Can anyone please tell me what i am doing wrong.
Xml File :
<?xml version="1.0" encoding="utf-8" ?>
<swes:InsertSensor
xmlns:swes="http://www.opengis.net/swes/2.0"
xmlns:sos="http://www.opengis.net/sos/2.0" >
<swes:metadata>
<sos:SosInsertionMetadata>
<sos:observationType>VALUE1</sos:observationType>
<sos:observationType>VALUE2</sos:observationType>
<sos:featureOfInterestType>VALUE3</sos:featureOfInterestType>
<sos:featureOfInterestType>VALUE4</sos:featureOfInterestType>
</sos:SosInsertionMetadata>
</swes:metadata>
</swes:InsertSensor>
My Classes :
namespace Problem1.Classes
{
[SerializableAttribute()]
[XmlTypeAttribute(Namespace = "http://www.opengis.net/swes/2.0")]
[XmlRootAttribute("InsertSensor", Namespace = "http://www.opengis.net/swes/2.0", IsNullable = false)]
public class InsertSensorType
{
[System.Xml.Serialization.XmlElementAttribute("metadata")]
public InsertSensorTypeMetadata[] metadata { get; set; }
}
[SerializableAttribute()]
[XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.opengis.net/swes/2.0")]
public class InsertSensorTypeMetadata
{
[XmlElement(ElementName = "SosInsertionMetadata", Type = typeof(SosInsertionMetadataType))]
public InsertionMetadataType InsertionMetadata { get; set; }
}
[XmlIncludeAttribute(typeof(SosInsertionMetadataType))]
[SerializableAttribute()]
[XmlTypeAttribute(Namespace = "http://www.opengis.net/swes/2.0")]
public abstract partial class InsertionMetadataType
{
}
[SerializableAttribute()]
[XmlTypeAttribute(Namespace = "http://www.opengis.net/sos/2.0")]
public partial class SosInsertionMetadataType : InsertionMetadataType
{
[System.Xml.Serialization.XmlElementAttribute("observationType", DataType = "anyURI")]
public string[] observationType { get; set; }
[System.Xml.Serialization.XmlElementAttribute("featureOfInterestType", DataType = "anyURI")]
public string[] featureOfInterestType { get; set; }
}
}
And here is my main code :
static void Main(string[] args)
{
XmlElement xmlRequest = null;
XmlDocument doc = new XmlDocument();
doc.Load("request.xml");
xmlRequest = doc.DocumentElement;
executeRequest(xmlRequest);
}
static void executeRequest(XmlElement xmlRequest)
{
InsertSensorType insertSensorRequest = ValidateRequest<InsertSensorType>(xmlRequest);
InsertSensorTypeMetadata[] _InsertSensorTypeMetadata = insertSensorRequest.metadata;
Console.WriteLine("Length of metadata :" + _InsertSensorTypeMetadata.Length);//1
foreach (InsertSensorTypeMetadata istm in _InsertSensorTypeMetadata)
{
SosInsertionMetadataType sos = istm.InsertionMetadata as SosInsertionMetadataType;
//sos is null
}
Console.Read();
}
static T ValidateRequest<T>(XmlElement xmlRequest) where T : class
{
string xml = xmlRequest.OuterXml;
StringReader reader = new StringReader(xml);
XmlSerializer serializer = new XmlSerializer(typeof(T));
//XmlSerializer serializer = new XmlSerializer(typeof(T), new Type[] { typeof(SosInsertionMetadataType) });
T typeInstance = (T)serializer.Deserialize(reader);
return typeInstance;
}
Try this
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Serialization;
using System.IO;
namespace ConsoleApplication1
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
InsertSensorType insertSensorType = new InsertSensorType() {
metadata = new Metadata() {
insertSensorTypeMetadata = new InsertSensorTypeMetadata() {
InsertionMetadata = new List<InsertionMetadataType>() {
new ObservationType() { value = "Value1"},
new ObservationType() { value = "Value2"},
new FeatureOfInterestType() { value = "Value3"},
new FeatureOfInterestType() { value = "Value4"}
}
}
}
};
XmlSerializer serializer = new XmlSerializer(typeof(InsertSensorType));
XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
ns.Add("swes","http://www.opengis.net/swes/2.0");
ns.Add("sos","http://www.opengis.net/sos/2.0");
StreamWriter writer = new StreamWriter(FILENAME);
serializer.Serialize(writer, insertSensorType, ns);
writer.Flush();
writer.Close();
writer.Dispose();
XmlSerializer xs = new XmlSerializer(typeof(InsertSensorType));
XmlTextReader reader = new XmlTextReader(FILENAME);
InsertSensorType newInsertSensorType = (InsertSensorType)xs.Deserialize(reader);
}
}
[XmlRoot(ElementName = "InsertSensor")]
public class InsertSensorType
{
[XmlElement("metadata")]
public Metadata metadata { get; set; }
}
[XmlRoot("metadata", Namespace = "http://www.opengis.net/swes/2.0")]
public class Metadata
{
[XmlElement("SosInsertionMetadata")]
public InsertSensorTypeMetadata insertSensorTypeMetadata { get; set; }
}
[XmlRoot("SosInsertionMetadata", Namespace = "http://www.opengis.net/sos/2.0")]
public class InsertSensorTypeMetadata
{
[XmlElement()]
public List<InsertionMetadataType> InsertionMetadata { get; set; }
}
[XmlInclude(typeof(ObservationType))]
[XmlInclude(typeof(FeatureOfInterestType))]
[Serializable]
[XmlRoot(Namespace = "http://www.opengis.net/sos/2.0")]
public class InsertionMetadataType
{
public string value { get; set; }
}
[Serializable]
[XmlRoot(ElementName = "observationType", Namespace = "http://www.opengis.net/sos/2.0")]
public class ObservationType : InsertionMetadataType
{
}
[Serializable]
[XmlRoot(ElementName = "featureOfInterestType", Namespace = "http://www.opengis.net/sos/2.0")]
public class FeatureOfInterestType : InsertionMetadataType
{
}
}
My solution is that :
added this line to over InsertionMetadata attribute in InsertSensorTypeMetadata class
[System.Xml.Serialization.XmlElement(ElementName = "SosInsertionMetadata", Type = typeof(SosInsertionMetadataType), Namespace = "http://www.opengis.net/sos/2.0")] // added
change my deserialize method
public static T ValidateRequest<T>(XmlElement element) where T : class
{
var serializer = new XmlSerializer(typeof(T));
return (T)serializer.Deserialize(new XmlNodeReader(element));
}
and changed way to print values
static void executeRequest(XmlElement xmlRequest)
{
InsertSensorType insertSensorRequest = ValidateRequest<InsertSensorType>(xmlRequest);
foreach (InsertSensorTypeMetadata istm in insertSensorRequest.metadata)
{
SosInsertionMetadataType sos = (SosInsertionMetadataType)istm.InsertionMetadata;
foreach(string s in sos.featureOfInterestType)
Console.WriteLine(s);
foreach (string s in sos.observationType)
Console.WriteLine(s);
}
}
I have one problem. I want to read JSON data from my local link and put it in an object class. My problem is that the object[] did not fill with data. Here is my code:
This is the serverdata.cs file with my object inside that I want to fill:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Runtime.Serialization;
namespace Διαχείριση
{
class serverdata
{
public προμηθευτέςRow[] Rows;
[DataContract(Name = "ΠρομηθευτέςResult")]
public struct προμηθευτέςRow
{
[DataMember(Name = "Κωδικός")]
public int Κωδικός { get; set; }
[DataMember(Name = "Όνομα")]
public string Όνομα { get; set; }
[DataMember(Name = "Επίθετο")]
public string Επίθετο { get; set; }
[DataMember(Name = "Τηλέφωνο")]
public string Τηλέφωνο { get; set; }
[DataMember(Name = "Διεύθυνση")]
public string Διεύθυνση { get; set; }
[DataMember(Name = "Mail")]
public string Mail { get; set; }
[DataMember(Name = "Προϊόντα")]
public string[] Προϊόντα { get; set; }
}
}
}
Then I have the Form.cs that I want to read the JSON data from my local server:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Runtime.Serialization.Json;
namespace Διαχείριση
{
public partial class Administator_Form : Form
{
serverdata ServerData;
public Administator_Form()
{
ServerData = new serverdata();
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
WebRequest request = WebRequest.Create(string.Format("mylocallink"));
WebResponse response = request.GetResponse();
Stream stream = request.GetResponse().GetResponseStream();
StreamReader sread = new StreamReader(stream);
//string sLine = sread.ReadLine();
//MessageBox.Show(sLine);
DataContractJsonSerializer json = new DataContractJsonSerializer(typeof(List<serverdata.προμηθευτέςRow>));
var result = (List<serverdata.προμηθευτέςRow>)json.ReadObject(stream);
ServerData.Rows = result.ToArray();
}
}
}
Now if I call for example MessageBox.Show(ServerData.Rows[0].Κωδικός.ToString()); I get an exception:
"An unhandled exception of type 'System.IndexOutOfRangeException' occurred in Project.exe
Additional information: Index was outside the bounds of the array."
So my problem is that result didn't fill ServerData.Rows.
Here is the JSON data:
{
"ΠρομηθευτέςResult": [
{
"Mail": "mail1",
"Όνομα": "name1",
"Διεύθυνση": "address1",
"Επίθετο": "epitheto1",
"Κωδικός": 1,
"Προϊόντα": [
"subproduct1.1",
"subproduct1.2"
],
"Τηλέφωνο": "1111111111"
},
{
"Mail": "mail2",
"Όνομα": "name2",
"Διεύθυνση": "address2",
"Επίθετο": "epitheto2",
"Κωδικός": 2,
"Προϊόντα": [
"subproduct2.1",
"subproduct2.2"
],
"Τηλέφωνο": "2222222222"
}
]
}
The issue is that you are trying to deserialize into a list, but in your JSON the row data is not at the root level--it is inside an object. To fix, you need to deserialize to your serverdata class directly. But first, you will need to make a couple of changes to the attributes:
Mark your serverdata class with [DataContract]
Mark the Rows property inside serverdata with [DataMember(Name = "ΠρομηθευτέςResult")]
Mark the προμηθευτέςRow struct with [DataContract]
Your class should look like this:
[DataContract]
class serverdata
{
[DataMember(Name = "ΠρομηθευτέςResult")]
public προμηθευτέςRow[] Rows { get; set; }
[DataContract]
public struct προμηθευτέςRow
{
[DataMember(Name = "Κωδικός")]
public int Κωδικός { get; set; }
[DataMember(Name = "Όνομα")]
public string Όνομα { get; set; }
[DataMember(Name = "Επίθετο")]
public string Επίθετο { get; set; }
[DataMember(Name = "Τηλέφωνο")]
public string Τηλέφωνο { get; set; }
[DataMember(Name = "Διεύθυνση")]
public string Διεύθυνση { get; set; }
[DataMember(Name = "Mail")]
public string Mail { get; set; }
[DataMember(Name = "Προϊόντα")]
public string[] Προϊόντα { get; set; }
}
}
Then, change your code to deserialize to your serverdata class:
DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(serverdata));
ServerData = (serverdata)ser.ReadObject(stream);
You can remove this line as it is no longer needed:
ServerData.Rows = result.ToArray();
After these changes you should find that the Rows array is filled correctly.
I have a class need to be serialized.
namespace serializedobject
{
[DataContract]
public class Class1
{
string string1_;
string string2_;
EntityA entity_;
[DataMember]
public string string3
{
get { return string1_; }
set { string1_ = value; }
}
[DataMember]
public string string2
{
get { return string2_; }
set { string2_ = value; }
}
[DataMember]
public EntityA Entity
{
get { return entity_; }
set { entity_ = value; }
}
public static Class1 FromXML(string desc)
{
using (MemoryStream ms = new MemoryStream())
{
StreamWriter writer = new StreamWriter(ms);
writer.Write(desc);
writer.Flush();
ms.Seek(0, 0);
DataContractSerializer ser = new DataContractSerializer(typeof(Class1));
return (Class1)ser.ReadObject(ms);
}
}
public string ToXML()
{
using (MemoryStream ms = new MemoryStream())
{
DataContractSerializer ser = new DataContractSerializer(typeof(Class1));
ser.WriteObject(ms, this);
ms.Seek(0, 0);
StreamReader reader = new StreamReader(ms);
return reader.ReadToEnd();
}
}
}
[DataContract]
public class EntityA
{
string name_;
[DataMember]
public string Name
{
get { return name_; }
set { name_ = value; }
}
}
}
it is works fine with FromXML and ToXML. one of serialized context like:
<Class1 xmlns="http://schemas.datacontract.org/2004/07/serializedobject" xmlns:i="http://www.w3.org/2001/XMLSchema-instance"><Entity><Name>az</Name></Entity><string2 i:nil="true"/><string3>test</string3></Class1>
Later I need to move class EntityA to another namespace "outside", now the serialized context like:
<Class1 xmlns="http://schemas.datacontract.org/2004/07/serializedobject" xmlns:i="http://www.w3.org/2001/XMLSchema-instance"><Entity xmlns:a="http://schemas.datacontract.org/2004/07/outside"><a:Name>az</a:Name></Entity><string2 i:nil="true"/><string3>test</string3></Class1>
but now the serialized xml which created before change namespace can't be deserialized correctly. I guess this is because of for class "EntityA" changed namespace (xmlns:a added).
does anybody run into the problem before? any suggestion?
You can stop the namespace being added to the XML by specifying [DataContract(Namespace="")]. This relies on you setting that attribute BEFORE you save any xml code.
You can use this approach only if you have not already serialized any data, so this is the approach you would use when first designing a class to be serialized.
(If you have already got serialized data that you must deal with, see the second part of my answer below.)
This code sample has the two classes called Demo in two different namespaces, Test1 and Test2.
We serialize the code using the class from one namespace, and deserialize it using the class from the other namespace:
using System;
using System.IO;
using System.Runtime.Serialization;
using System.Xml;
namespace ConsoleApp1
{
namespace Test1
{
[DataContract(Namespace="")]
public sealed class Demo
{
[DataMember]
public string Value { get; set; }
}
}
namespace Test2
{
[DataContract(Namespace="")]
public sealed class Demo
{
[DataMember]
public string Value { get; set; }
}
}
sealed class Program
{
private void run()
{
string filename = Path.GetTempFileName();
var demo1 = new Test1.Demo {Value = "DEMO"};
ToFile(filename, demo1);
var demo2 = FromFile<Test2.Demo>(filename);
Console.WriteLine(demo2.Value);
}
public static void ToFile(string filename, object obj)
{
DataContractSerializer serializer = new DataContractSerializer(obj.GetType());
using (var streamWriter = File.CreateText(filename))
using (var xmlWriter = XmlWriter.Create(streamWriter, new XmlWriterSettings{Indent = true}))
{
serializer.WriteObject(xmlWriter, obj);
}
}
public static T FromFile<T>(string filename)
{
DataContractSerializer serializer = new DataContractSerializer(typeof(T));
using (var textReader = File.OpenText(filename))
using (var xmlReader = XmlReader.Create(textReader))
{
return (T)serializer.ReadObject(xmlReader);
}
}
[STAThread]
static void Main(string[] args)
{
new Program().run();
}
}
}
If you have already serialized data without the Namespace="" attribute, then you will need instead to apply the appropriate namespace to the new class:
namespace Test1
{
[DataContract]
public sealed class Demo
{
[DataMember]
public string Value { get; set; }
}
}
namespace Test2
{
// Note the namespace includes both nested namespaces, i.e. ConsoleApp1.Test1
[DataContract(Namespace="http://schemas.datacontract.org/2004/07/ConsoleApp1.Test1")]
public sealed class Demo
{
[DataMember]
public string Value { get; set; }
}
}
I would like to deserialize the following XML into the following type. How do I map the status correctly? (it is currently not mapped and remains null after the deserialization process)
<?xml version="1.0" encoding="UTF-8"?>
<job:job-status xsi:schemaLocation="http://marklogic.com/xdmp/job-status job-status.xsd" xmlns:job="http://marklogic.com/xdmp/job-status" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<job:forest>
<job:forest-name>FOREST2</job:forest-name>
<job:forest-id>1168048654236455340</job:forest-id>
<job:status>completed</job:status>
<job:journal-archiving>false</job:journal-archiving>
</job:forest>
</job:job-status>
[XmlRoot("job-status", Namespace = "http://marklogic.com/xdmp/job-status")]
public class DatabaseRestoreStatus
{
[XmlElement("status")]
public string Status { get; set; }
}
Using DataContract Serializer worked for me. I also had to create one more class.
using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.Serialization;
namespace SandboxConoleApp
{
internal class Program
{
private static void Main(string[] args)
{
DatabaseRestoreStatus data = null;
using (var stream = File.Open("test.xml",FileMode.Open))
{
var formatter = new DataContractSerializer(typeof(DatabaseRestoreStatus));
data = (DatabaseRestoreStatus)formatter.ReadObject(stream);
}
}
}
[DataContract(Name = "job-status", Namespace = "http://marklogic.com/xdmp/job-status")]
public class DatabaseRestoreStatus
{
[DataMember(Name = "forest")]
public Forest Forest { get; set; }
}
[DataContract(Name = "forest", Namespace = "http://marklogic.com/xdmp/job-status")]
public class Forest
{
[DataMember(Name = "status")]
public string Status { get; set; }
}
}