How to Deserialize this Xml file? - c#

I have this Xml file, and I need to Deserialize it back to a class. The problem is: what is the right structure/design of this class considering that the count of the Xml element (RowInfo) is not constant?
The Xml File:
<?xml version="1.0"?>
<SomeObject xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" >
<Layers>
<Layer Id="0">
<RowInfo>1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1</RowInfo>
<RowInfo>1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1</RowInfo>
<RowInfo>1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1</RowInfo>
<RowInfo>1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1</RowInfo>
<RowInfo>1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1</RowInfo>
<RowInfo>1,1,1,0,0,1,1,1,1,1,1,1,1,1,1,0,0,1,1,1</RowInfo>
<RowInfo>1,1,1,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1</RowInfo>
<RowInfo>1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1</RowInfo>
<RowInfo>1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1</RowInfo>
<RowInfo>1,1,1,1,1,1,1,1,1,0,0,1,1,1,1,1,1,1,1,1</RowInfo>
<RowInfo>1,1,1,0,0,1,1,1,1,1,1,1,1,1,1,1,0,0,1,1</RowInfo>
<RowInfo>1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1</RowInfo>
<RowInfo>1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1</RowInfo>
<RowInfo>1,1,1,1,1,1,1,1,1,0,0,1,1,1,1,1,1,1,1,1</RowInfo>
<RowInfo>1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1</RowInfo>
<RowInfo>1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1</RowInfo>
<RowInfo>1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1</RowInfo>
<RowInfo>1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1</RowInfo>
<RowInfo>1,1,1,0,0,1,1,1,1,1,1,1,1,1,0,0,1,0,0,1</RowInfo>
<RowInfo>1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1</RowInfo>
</Layer>
</Layers>
</SomeObject>
Appreciate your help.
Thanks.
Edit1:also considering that (Layers) may contains more than one layer.

Something like the following - names will need to be changed to protect the innocent:
Class structure after comment
public class SomeObject
{
public List<Layer> Layers {get;set;}
}
public class Layer
{
public int Id {get;set;}
public List<RowInfo> RowInfos {get;set;}
}
public class RowInfo
{
public List<Row> Rows {get;set;}
}
public class Row
{
public int RowData {get;set;}
}

This should work as you want:
public class SomeObject
{
public List<Layer> Layers { get; set; }
}
public class Layer
{
[XmlAttribute]
public int Id { get; set; }
[XmlElement("RowInfo")]
public List<RowInfo> RowInfos { get; set; }
}
public class RowInfo
{
[XmlText]
public string Info { get; set; } // you'll need to parse the list of ints manually
}
The only difference is the encoding but you should be able to work around it.

If the count of RowInfo is not constant, use a List in your class.

XmlSerializer serializer = new XmlSerializer(typeof(SomeObject));
you can use XmlSerializer with the following code and call Deserialize :)
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:2.0.50727.4952
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
using System.Xml.Serialization;
//
// This source code was auto-generated by xsd, Version=2.0.50727.3038.
//
/// <remarks/>
[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 SomeObject {
private SomeObjectLayers layersField;
/// <remarks/>
public SomeObjectLayers Layers {
get {
return this.layersField;
}
set {
this.layersField = value;
}
}
}
/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "2.0.50727.3038")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)]
public partial class SomeObjectLayers {
private SomeObjectLayersLayer layerField;
/// <remarks/>
public SomeObjectLayersLayer Layer {
get {
return this.layerField;
}
set {
this.layerField = value;
}
}
}
/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "2.0.50727.3038")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)]
public partial class SomeObjectLayersLayer {
private decimal[] rowInfoField;
private int idField;
private bool idFieldSpecified;
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute("RowInfo")]
public decimal[] RowInfo {
get {
return this.rowInfoField;
}
set {
this.rowInfoField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlAttributeAttribute()]
public int Id {
get {
return this.idField;
}
set {
this.idField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlIgnoreAttribute()]
public bool IdSpecified {
get {
return this.idFieldSpecified;
}
set {
this.idFieldSpecified = value;
}
}
}

I would say use LINQ-to-Xml. Have a constructor on your object that can take an xlement then do
Something along the lines of
public class YourObject()
{
public IEnumerable<Layer> Layers { get; set; }
public int Id { get; set; }
public YourObj(XElement x)
{
this.Id = int.Parse(x.Attribute("Id").ToString());
this.Layers = from layer in x.Elements("Layer")
select new Layer(layer);
}
}
var objs = (from c in XElement.Load("your.xml").Elements("layer")
select new YourObject(c)).ToList() ;

Checkout a tool called XSD.exe it come with visual studio and will allow you to generate code form an xml file.
You should see it on the program files menu next to visual studio.

Related

Incorrect deserialization of SOAP message in .NET app

I am working on converting an existing application from .NET Framework to .NET 6. Deserialization of SOAP message no longer works as expected.
I have the following response message:
<?xml version="1.0" encoding="utf-16"?>
<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
<s:Header xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" />
<S:Body>
<ns2:findAgreementResponse
xmlns:ns2="example.webservices.licensing.secure"
xmlns:ns3="example.webservices.exceptions">
<return>
<description>Standard</description>
<idLicenseAgreement>1234</idLicenseAgreement>
</return>
</ns2:findAgreementResponse>
</S:Body>
</S:Envelope>
With the .NET Framework, the code generated when I added a service reference included this:
[System.Xml.Serialization.XmlIncludeAttribute(typeof(agreement))]
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.Xml", "4.7.3221.0")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(Namespace="http://example.org/licensing/")]
public partial class messageBase {
private System.Xml.XmlElement[] anyField;
private string messageIdField;
[System.Xml.Serialization.XmlAnyElementAttribute()]
public System.Xml.XmlElement[] Any {
get { return this.anyField; }
set { this.anyField = value; }
}
[System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
public string messageId {
get { return this.messageIdField; }
set { this.messageIdField = value; }
}
}
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.Xml", "4.7.3221.0")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(Namespace="http://example.org/licensing/")]
public partial class agreement : messageBase {
private string descriptionField;
private long idLicenseAgreementField;
private bool idLicenseAgreementFieldSpecified;
[System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
public string description {
get { return this.descriptionField; }
set { this.descriptionField = value; }
}
[System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
public long idLicenseAgreement {
get { return this.idLicenseAgreementField; }
set { this.idLicenseAgreementField = value; }
}
[System.Xml.Serialization.XmlIgnoreAttribute()]
public bool idLicenseAgreementSpecified {
get { return this.idLicenseAgreementFieldSpecified; }
set { this.idLicenseAgreementFieldSpecified = value; }
}
}
[System.Web.Services.Protocols.SoapDocumentMethodAttribute("", RequestNamespace="example.webservices.licensing.secure", ResponseNamespace="example.webservices.licensing.secure", Use=System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle=System.Web.Services.Protocols.SoapParameterStyle.Wrapped)]
[return: System.Xml.Serialization.XmlElementAttribute("return", Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
public agreement findAgreement([System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)] string arg0) {
object[] results = this.Invoke("findAgreement", new object[] {
arg0});
return ((agreement)(results[0]));
}
This worked well, the response was properly deserialized (when calling the findAgreement method). When something was not expected (there are many methods and responses), it was added to the Any array from messageBase.
After migrating to .NET 6, adding the service resulted in the following code:
[System.SerializableAttribute()]
[System.Xml.Serialization.XmlIncludeAttribute(typeof(agreement))]
[System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "2.0.3")]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.Xml.Serialization.XmlTypeAttribute(Namespace="http://example.org/licensing/")]
public partial class messageBase
{
private System.Xml.XmlElement[] anyField;
private string messageIdField;
[System.Xml.Serialization.XmlAnyElementAttribute(Order=0)]
public System.Xml.XmlElement[] Any
{
get { return this.anyField; }
set { this.anyField = value; }
}
[System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=1)]
public string messageId
{
get { return this.messageIdField; }
set { this.messageIdField = value; }
}
}
[System.SerializableAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "2.0.3")]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.Xml.Serialization.XmlTypeAttribute(Namespace="http://example.org/licensing/")]
public partial class agreement : messageBase
{
private string descriptionField;
private long idLicenseAgreementField;
private bool idLicenseAgreementFieldSpecified;
[System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=0)]
public string description
{
get { return this.descriptionField; }
set { this.descriptionField = value; }
}
[System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=1)]
public long idLicenseAgreement
{
get { return this.idLicenseAgreementField; }
set { this.idLicenseAgreementField = value; }
}
[System.Xml.Serialization.XmlIgnoreAttribute()]
public bool idLicenseAgreementSpecified
{
get { return this.idLicenseAgreementFieldSpecified; }
set { this.idLicenseAgreementFieldSpecified = value; }
}
}
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "2.0.3")]
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
[System.ServiceModel.MessageContractAttribute(WrapperName="findAgreementResponse", WrapperNamespace="example.webservices.licensing.secure", IsWrapped=true)]
public partial class findAgreementResponse
{
[System.ServiceModel.MessageBodyMemberAttribute(Namespace="example.webservices.licensing.secure", Order=0)]
[System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
public agreement #return;
public findAgreementResponse()
{
}
public findAgreementResponse(agreement #return)
{
this.#return = #return;
}
}
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
findAgreementResponse findAgreement(findAgreementRequest request)
{
return base.Channel.findAgreement(request);
}
What happens now is that the description and idLicenseAgreement properties are not filled in. Instead, the Any array from the base class contains both these XML elements:
<description>Standard</description>
<idLicenseAgreement>1234</idLicenseAgreement>
If I remove the messageBase base class, parsing occurs correctly, and the agreement object is properly filled in with the data from the SOAP response.
I expect this to be a namespace issue but I was unable to figure it out.
I figured out the problem was the explicit ordering of elements. In the code generated by Svcutil in .NET 6, all the XML elements are attributed like this:
[System.Xml.Serialization.XmlAnyElementAttribute(Order=0)]
Once I removed the Order property from all of them, deserialization worked as expected.

NULL-Values when deserializing XML

I try to deserialize different XML docs which are build according to the same schema and yes, I'm a newby to this topic. I managed to retrieve some auto-generated Code from using xsd-files as “type definition language” (VS2013) and for me it looks ok and basically it’s working which means I can start the program. However, there is no output of my program and by debugging it I can see that the most important fields are not populated. Here is the situation (the original generated code and the XML are of course much longer but I cut to the classes which produce the problem):
XML:
<?xml version="1.0" encoding="UTF-8"?>
<mainDatas
xmlns="http://www.myNamespace.com/"
xmlns:ons="http://www.myOtherNamespace.com/"
xmlns:aan="http://www.andAnotherNamespace.com/">
<contains>
<ons:FeatureCollection aan:id="UHL">
<aan:boundedBy>999.9</aan:boundedBy>
<aan:featureMember>
<myClass1 aan:id="XXX0001">
</myClass1>
</aan:featureMember>
<myClass2 aan:id="XXX0002">
</myClass2>
</aan:featureMember>
<myClass1 aan:id="XXX0003">
</myClass1>
</aan:featureMember>
</ons:FeatureCollection>
</contains>
</mainDatas>
C# (auto-generated):
[System.CodeDom.Compiler.GeneratedCodeAttribute("MSBuild", "12.0.30723.0")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(Namespace="http://www.myNamespace.com/")]
[System.Xml.Serialization.XmlRootAttribute("mainDatas", Namespace="http://www.myNamespace.com/", IsNullable=false)]
public partial class mainDatas
{
private mainDatasContains containField;
public mainDatasContains contain
{
get
{
return this.containField;
}
set
{
this.containField = value;
}
}
}
[System.CodeDom.Compiler.GeneratedCodeAttribute("MSBuild", "12.0.30723.0")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true, Namespace="http://www.myNamespace.com/")]
public partial class mainDatasContains
{
private FeatureCollectionType1 featureCollectionField;
[System.Xml.Serialization.XmlElementAttribute(Namespace="http://www.myOtherNamespace.com/")]
public FeatureCollectionType1 FeatureCollection
{
get
{
return this.featureCollectionField;
}
set
{
this.featureCollectionField = value;
}
}
}
[System.CodeDom.Compiler.GeneratedCodeAttribute("MSBuild", "12.0.30723.0")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(TypeName="FeatureCollectionType", Namespace="http://www.myOtherNamespace.de/")]
[System.Xml.Serialization.XmlRootAttribute("FeatureCollection", Namespace="http://www.myOtherNamespace.de/", IsNullable=false)]
public partial class FeatureCollectionType1
{
private string lockIdField;
private FeaturePropertyType[] featureMemberField;
[System.Xml.Serialization.XmlAttributeAttribute()]
public string lockId
{
get
{
return this.lockIdField;
}
set
{
this.lockIdField = value;
}
}
[System.Xml.Serialization.XmlElementAttribute("featureMember")]
public FeaturePropertyType[] featureMember
{
get
{
return this.featureMemberField;
}
set
{
this.featureMemberField = value;
}
}
}
[System.CodeDom.Compiler.GeneratedCodeAttribute("MSBuild", "12.0.30723.0")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(Namespace="http://www.andAnotherNamespace.com/")]
[System.Xml.Serialization.XmlRootAttribute("featureMember", Namespace="http://www.andAnotherNamespace.com/", IsNullable=false)]
public partial class FeaturePropertyType
{
private AbstractFeatureType itemField;
private bool ownsField;
public FeaturePropertyType()
{
this.ownsField = false;
}
[System.Xml.Serialization.XmlElementAttribute("DynamicFeature", typeof(DynamicFeatureType))]
[System.Xml.Serialization.XmlElementAttribute("FeatureCollection", typeof(FeatureCollectionType))]
[System.Xml.Serialization.XmlElementAttribute("Observation", typeof(ObservationType))]
public AbstractFeatureType Item
{
get
{
return this.itemField;
}
set
{
this.itemField = value;
}
}
[System.Xml.Serialization.XmlAttributeAttribute()]
[System.ComponentModel.DefaultValueAttribute(false)]
public bool owns
{
get
{
return this.ownsField;
}
set
{
this.ownsField = value;
}
}
}
[System.Xml.Serialization.XmlIncludeAttribute(typeof(myClass1))]
[System.Xml.Serialization.XmlIncludeAttribute(typeof(myClass2))]
[System.CodeDom.Compiler.GeneratedCodeAttribute("MSBuild", "12.0.30723.0")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(Namespace="http://www.andAnotherNamespace.com/")]
[System.Xml.Serialization.XmlRootAttribute(Namespace="http://www.andAnotherNamespace.com/", IsNullable=true)]
public abstract partial class AbstractFeatureType
{
private BoundingShapeType boundedByField;
private LocationPropertyType itemField;
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(IsNullable=true)]
public BoundingShapeType boundedBy
{
get
{
return this.boundedByField;
}
set
{
this.boundedByField = value;
}
}
[System.CodeDom.Compiler.GeneratedCodeAttribute("MSBuild", "12.0.30723.0")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(Namespace="http://myNamespace.com")]
[System.Xml.Serialization.XmlRootAttribute("myClass1", Namespace="http://www.myNamespace.com/", IsNullable=false)]
public partial class myClass1 : AbstractFeatureType
{
}
[System.CodeDom.Compiler.GeneratedCodeAttribute("MSBuild", "12.0.30723.0")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(Namespace="http://myNamespace.com")]
[System.Xml.Serialization.XmlRootAttribute("myClass2", Namespace="http://www.myNamespace.com/", IsNullable=false)]
public partial class myClass2 : AbstractFeatureType
{
}
Sorry for posting that much auto-generated code. I tried to omitt as much as possible but since I'm quite clueless I'm not sure what is necessary and what not.
And now my piece of work:
XmlSerializer serializer = new XmlSerializer(typeof(mainDatas));
XmlTextReader reader = new XmlTextReader(#".\myData.xml");
mainDatas dataObject = (mainDatas)serializer.Deserialize(reader);
FeaturePropertyType[] allObjects = dataObject.contain.FeatureCollection.featureMember;
foreach(FeaturePropertyType feature in allObjects)
{
if (feature.Item != null && feature.Item.GetType() == typeof(myClass1))
{
this.doSomething((myClass1)feature.Item));
}
else
{
this.doSomethingElse();
}
}
While debugging it shows me that allObjects contains 3 items of type FeaturePropertyType (i.e. the number of myClass1 and myClass2 in the xml-sheet as suspected) but the property Item of these items is null.
When I searched in the Internet many people suggested that it might be a problem with the namespaces. So I experimented a little bit with it changing it back and forth but without success. And I don't think it's a good idea to change to much in the auto-generated code, anyways.
I would be glad if anyone could give me some suggestions about this issue.
Greetings
TM
EDIT:
I had to edit my code because I forgot to write the inheritance of AbstractFeatureType by myClass1 and myClass2.
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)
{
MainDatas mainDatas = new MainDatas() {
contains = new MainDatasContains() {
featureCollection = new FeatureCollection(){
id = "UHL",
boundedBy = 999.9,
featureMembers = new List<FeatureMember>() {
new FeatureMember() {
myClass1 = new MyClass1() {
id = "XXX0001"
}
},
new FeatureMember() {
myClass2 = new MyClass2() {
id = "XXX0001"
}
},
new FeatureMember() {
myClass1 = new MyClass1() {
id = "XXX0003"
}
}
}
}
}
};
XmlSerializer serializer = new XmlSerializer(typeof(MainDatas));
StreamWriter writer = new StreamWriter(FILENAME);
XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
ns.Add("aan", "http://www.andAnotherNamespace.com/");
ns.Add("ons", "http://www.myOtherNamespace.com/");
ns.Add("", "http://www.myNamespace.com/");
serializer.Serialize(writer, mainDatas, ns);
writer.Flush();
writer.Close();
writer.Dispose();
XmlSerializer xs = new XmlSerializer(typeof(MainDatas));
XmlTextReader reader = new XmlTextReader(FILENAME);
MainDatas newMainDatas = (MainDatas)xs.Deserialize(reader);
}
}
[XmlRoot("mainDatas", Namespace = "http://www.myNamespace.com/")]
public class MainDatas
{
[XmlElement("contains")]
public MainDatasContains contains { get; set; }
}
[XmlRoot("contains")]
public class MainDatasContains
{
[XmlElement("FeatureCollection", Namespace = "http://www.myOtherNamespace.com/")]
public FeatureCollection featureCollection { get; set; }
}
[XmlRoot(ElementName = "FeatureCollection")]
public class FeatureCollection
{
[XmlAttribute("id", Namespace = "http://www.andAnotherNamespace.com/")]
public string id { get; set; }
[XmlElement("boundedBy", Namespace = "http://www.andAnotherNamespace.com/")]
public double boundedBy { get; set; }
[XmlElement("featureMember", Namespace = "http://www.andAnotherNamespace.com/")]
public List<FeatureMember> featureMembers { get; set; }
}
[XmlRoot("featureMember")]
public class FeatureMember
{
[XmlElement("myClass1")]
public MyClass1 myClass1 { get; set; }
[XmlElement("myClass2")]
public MyClass2 myClass2 { get; set; }
}
[XmlRoot("myClass1")]
public class MyClass1
{
[XmlAttribute("id", Namespace = "http://www.andAnotherNamespace.com/")]
public string id { get; set; }
}
[XmlRoot("myClass2")]
public class MyClass2
{
[XmlAttribute("id")]
public string id { get; set; }
}
}
​

How to add XML attributes in XML Serialization C#

Hi am having some problems in XML serialization of XML attributes, following are some details of class file generated from XSD.
/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.0.30319.17929")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true, Namespace="http://tempuri.org/UpdatePolicy.xsd")]
public partial class policyClasses {
private policyClassesClass[] classField;
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute("class")]
public policyClassesClass[] #class {
get {
return this.classField;
}
set {
this.classField = value;
}
}
}
/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.0.30319.17929")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true, Namespace="http://tempuri.org/UpdatePolicy.xsd")]
public partial class policyClassesClass {
private string company_idField;
private string deductable_rateField;
private string max_limitField;
private string class_nameField;
private string class_numberField;
private policyClassesClassCchi_class_number cchi_class_numberField;
private policyClassesClassAction_type action_typeField;
private bool action_typeFieldSpecified;
/// <remarks/>
public string company_id {
get {
return this.company_idField;
}
set {
this.company_idField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(DataType="positiveInteger")]
public string deductable_rate {
get {
return this.deductable_rateField;
}
set {
this.deductable_rateField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(DataType="positiveInteger")]
public string max_limit {
get {
return this.max_limitField;
}
set {
this.max_limitField = value;
}
}
/// <remarks/>
public string class_name {
get {
return this.class_nameField;
}
set {
this.class_nameField = value;
}
}
/// <remarks/>
public string class_number {
get {
return this.class_numberField;
}
set {
this.class_numberField = value;
}
}
/// <remarks/>
public policyClassesClassCchi_class_number cchi_class_number {
get {
return this.cchi_class_numberField;
}
set {
this.cchi_class_numberField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlAttributeAttribute()]
public policyClassesClassAction_type action_type {
get {
return this.action_typeField;
}
set {
this.action_typeField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlIgnoreAttribute()]
public bool action_typeSpecified {
get {
return this.action_typeFieldSpecified;
}
set {
this.action_typeFieldSpecified = value;
}
}
}
/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.0.30319.17929")]
[System.SerializableAttribute()]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true, Namespace="http://tempuri.org/UpdatePolicy.xsd")]
public enum policyClassesClassCchi_class_number {
/// <remarks/>
[System.Xml.Serialization.XmlEnumAttribute("1")]
Item1,
/// <remarks/>
[System.Xml.Serialization.XmlEnumAttribute("2")]
Item2,
/// <remarks/>
[System.Xml.Serialization.XmlEnumAttribute("3")]
Item3,
/// <remarks/>
[System.Xml.Serialization.XmlEnumAttribute("4")]
Item4,
}
/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.0.30319.17929")]
[System.SerializableAttribute()]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true, Namespace="http://tempuri.org/UpdatePolicy.xsd")]
public enum policyClassesClassAction_type {
/// <remarks/>
[System.Xml.Serialization.XmlEnumAttribute("10")]
Item10,
/// <remarks/>
[System.Xml.Serialization.XmlEnumAttribute("1")]
Item1,
I managed to generate XML based on this class by serialization, but not having any idea to add the XML attribute to the XML generated, i supposed to get an output as below.
<classes>
<class action_type="10">
<company_id>999</company_id>
<deductable_rate>20</deductable_rate>
<max_limit>800</max_limit>
<class_name>Class A</class_name>
<class_number>1</class_number>
<cchi_class_number>2</cchi_class_number>
</class>
how to add the attribute to the element <class action_type = "10">
from /// <remarks/>
[System.Xml.Serialization.XmlAttributeAttribute()]
public policyClassesClassAction_type action_type {
get {
return this.action_typeField;
}
set {
this.action_typeField = value;
}
}
Please somebody help me on this to manage my deadlines, also tell me if anything is not clear for the valuable responses
Joe
Notice that the generated class is marked partial.
Add another class right next to the generated one in your project and give it a similar name, such as GeneratedClasses.addon.cs. Add this in your new file:
public partial class policyClasses {
[System.Xml.Serialization.XmlAttribute]
public policyClassesClassAction_type action_type { get;set;}
}

c#: How to create serializable c# class to reflect XML file with dynamic sub-element?

Can anyone suggest how to create a c# class to reflect the following example of XML structure please? Basically, the sub-element within the element Value can contain either Integer or String elements.
<Preferences>
<Preference>
<Tag>CY3A</Tag>
<Precedence>XML</Precedence>
<Value>
<Length>4</Length>
<Integer>0</Integer>
</Value>
</Preference>
<Preference>
<Tag>CYRV</Tag>
<Precedence>XML</Precedence>
<Value>
<Length>16</Length>
<String>0000 00 #00000</String>
</Value>
</Preference>
</Preferences>
I have tried to define the class as follows but it didn't result in what I am looking for. It generates the unwanted d element.
public class ProgrammingConfiguration
{
public int Version { get; set; }
public preferences Preferences { get; set; }
}
public class preferences
{
public preference Preference { get; set; }
}
public class preference
{
public string Tag { get; set; }
public string Precedence { get; set; }
public value Value { get; set; }
}
public class value
{
[XmlElement]
public int Length;
[XmlElement(Type = typeof(Integer)),
XmlElement(Type = typeof(HexBinary))]
public object datafield;
}
public class Integer
{
public string d;
}
public class String
{
public string d;
}
I normally create an xsd and then use the xsd.exe tool to create a .cs class file from the xsd.
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.269
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
using System.Xml.Serialization;
//
// This source code was auto-generated by xsd, Version=4.0.30319.1.
//
/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.0.30319.1")]
[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 Preferences {
private PreferencesPreference[] itemsField;
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute("Preference", Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
public PreferencesPreference[] Items {
get {
return this.itemsField;
}
set {
this.itemsField = value;
}
}
}
/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.0.30319.1")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)]
public partial class PreferencesPreference {
private string tagField;
private string precedenceField;
private PreferencesPreferenceValue[] valueField;
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
public string Tag {
get {
return this.tagField;
}
set {
this.tagField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
public string Precedence {
get {
return this.precedenceField;
}
set {
this.precedenceField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute("Value", Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
public PreferencesPreferenceValue[] Value {
get {
return this.valueField;
}
set {
this.valueField = value;
}
}
}
/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.0.30319.1")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)]
public partial class PreferencesPreferenceValue {
private string lengthField;
private string stringField;
private string integerField;
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
public string Length {
get {
return this.lengthField;
}
set {
this.lengthField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
public string String {
get {
return this.stringField;
}
set {
this.stringField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
public string Integer {
get {
return this.integerField;
}
set {
this.integerField = value;
}
}
}
xsd.exe is a utility that comes with Visual Studio....
Have a look at http://quickstart.developerfusion.co.uk/quickstart/howto/doc/xmlserialization/XSDFromCls.aspx
But you can do it from the XML too
c:\temp>xsd test.xml
Microsoft (R) Xml Schemas/DataTypes support utility
[Microsoft (R) .NET Framework, Version 4.0.30319.1]
Copyright (C) Microsoft Corporation. All rights reserved.
Writing file 'c:\temp\test.xsd'.
c:\temp>xsd test.xsd /classes
Microsoft (R) Xml Schemas/DataTypes support utility
[Microsoft (R) .NET Framework, Version 4.0.30319.1]
Copyright (C) Microsoft Corporation. All rights reserved.
Writing file 'c:\temp\test.cs'.
To solve the string vs integer problem, you can add an xs:choice field to your xsd, this will generate an "Item" which you can then cast as a Int or String as appropriate. Have a look at http://msdn.microsoft.com/en-us/library/exchange/bb426064(v=exchg.140).aspx
<xs:complexType name="FindItemParentType">
<xs:choice>
<xs:element name="Items" type="t:ArrayOfRealItemsType"/>
<xs:element name="Groups" type="t:ArrayOfGroupedIetmsType"/>
</xs:choice>
<xs:attributeGroup ref="t:FindResponsePagingAttributes"/>
</xs:complexType>
FindItemParentType fipt = new FindItemParentType();
object obj = fipt.Item;
if (obj is ArrayOfGroupedItemsType)
{
ArrayOfGroupedItemsType groupedItems = (obj as ArrayOfGroupedItemsType);
//TODO: Write code to handle grouped items.
}
else if (obj is ArrayOfRealItemsType)
{
ArrayOfRealItemsType items = (obj as ArrayOfRealItemsType);
//TODO: Write code to handle items.
}

Using XmlSerializer to create a non-standard element

I'm trying to create an XML output file to import into another program. The example XML file I was given looks like this:
<SalesOrder>
<OrderHeader>
<BillTo>
<EntityID>1234</EntityID>
</BillTo>
</OrderHeader>
<LineItemList>
<OrderLineComment>
<LineItemID>1</LineItemID>
</OrderLineComment>
<LineItem>
...
</LineItem>
<LineItem>
...
</LineItem>
<LineItem>
...
</LineItem>
...
</LineItemList>
</SalesOrder>
I have a C# project that is able to output this type of file using an XmlSerializer with the exception of this part:
<LineItemList>
<OrderLineComment>
<LineItemID>1</LineItemID>
</OrderLineComment>
The LineItemList section is simply a list of LineItems, but at the beginning of the LineItemList there is tacked this different element OrderLineComment.
If I represent this as an array of LineItems, then it looks the same except it's missing the OrderLineComment. If I represent this as a new object LineItemList containing an OrderLineComment and an array of LineItems, I get this:
<LineItemList>
<OrderLineComment>
<LineItemID>1</LineItemID>
</OrderLineComment>
<LineItems>
<LineItem>
...
</LineItem>
...
</LineItems>
Which has what I want, except it wraps all the LineItems with the <LineItems> tag, which isn't what I want either.
So what I'm wondering is:
Is there a way to do this via XmlSerializer? If so, how?
If there isn't, and I have to rewrite the code to use something other than XmlSerializer, what would be the best way to do this and why?
Thanks in advance.
You can make a OrderLineComment and LineItem derive from a common base class :
public abstract class LineItemBase
{
...
}
public class LineItem : LineItemBase
{
...
}
public class OrderLineComment : LineItemBase
{
...
}
Then declare the LineItemList property as a collection of LineItemBase objects, and use the XmlArrayItem attribute to specify which types can be included in the collection:
[XmlArrayItem(typeof(LineItem))]
[XmlArrayItem(typeof(OrderLineComment))]
public List<LineItemBase> LineItemList { get; set; }
This should achieve what you want
You can always implement IXmlSerializable interface on your type. It allows serialization of any complexity and it works with XmlSerializer.
Edit:
Here is the example of generated code if you want to achieve it with standard attributes. I created xsd from your xml and generated the code with XSD.exe.
[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 SalesOrder {
private OrderHeader orderHeaderField;
private LineItemList lineItemListField;
/// <remarks/>
public OrderHeader OrderHeader {
get {
return this.orderHeaderField;
}
set {
this.orderHeaderField = value;
}
}
/// <remarks/>
public LineItemList LineItemList {
get {
return this.lineItemListField;
}
set {
this.lineItemListField = value;
}
}
}
/// <remarks/>
[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 OrderHeader {
private BillTo billToField;
/// <remarks/>
public BillTo BillTo {
get {
return this.billToField;
}
set {
this.billToField = value;
}
}
}
/// <remarks/>
[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 BillTo {
private short entityIDField;
/// <remarks/>
public short EntityID {
get {
return this.entityIDField;
}
set {
this.entityIDField = value;
}
}
}
/// <remarks/>
[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 LineItemList {
private OrderLineComment orderLineCommentField;
private string[] lineItemField;
/// <remarks/>
public OrderLineComment OrderLineComment {
get {
return this.orderLineCommentField;
}
set {
this.orderLineCommentField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute("LineItem")]
public string[] LineItem {
get {
return this.lineItemField;
}
set {
this.lineItemField = value;
}
}
}
/// <remarks/>
[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 OrderLineComment {
private sbyte lineItemIDField;
/// <remarks/>
public sbyte LineItemID {
get {
return this.lineItemIDField;
}
set {
this.lineItemIDField = value;
}
}
}

Categories