Incorrect XML structure c# [duplicate] - c#

I am having an issue with serializing and object, I can get it to create all the correct outputs except for where i have an Element that needs a value and an attribute. Here is the required output:
<Root>
<Method>Retrieve</Method>
<Options>
<Filter>
<Times>
<TimeFrom>2009-06-17</TimeFrom>
</Times>
<Document type="word">document name</Document>
</Filter>
</Options>
</AdCourierAPI>
I can build all of it but can not find a way to set the Document type attribute, here is a segment of the object class
[XmlRoot("Root"), Serializable]
public class Root
{
[XmlElement("Method")]
public string method="RetrieveApplications";
[XmlElement("Options")]
public _Options Options;
}
public class _Options
{
[XmlElement("Filter")]
public _Filter Filter;
}
public class _Filter
{
[XmlElement("Times")]
public _Times Times;
[XmlElement("Documents")]
public string Documents;
}
which gives me:
<Document>document name</Document>
rather than:
<Document type="word">document name</Document>
but I can not find a way to correct this, please advise.
Thanks

Where do you have the type stored?
Normally you could have something like:
class Document {
[XmlAttribute("type")]
public string Type { get; set; }
[XmlText]
public string Name { get; set; }
}
public class _Filter
{
[XmlElement("Times")]
public _Times Times;
[XmlElement("Document")]
public Document Document;
}

The string class doesn't have a type property, so you can't use it to create the desired output. You should create a Document class instead :
public class Document
{
[XmlText]
public string Name;
[XmlAttribute("type")]
public string Type;
}
And you should change the Document property to type Document

It sounds like you need an extra class:
public class Document
{
[XmlAttribute("type")]
public string Type { get; set; }
[XmlText]
public string Name { get; set; }
}
Where an instance (in the example) would have Type = "word" and Name = "document name"; documents would be a List<Document>.
By the way - public fields are rarely a good idea...

You can use XmlWriter instead XmlSerialization to get this effect.
It is more complex but if you have a lot of strings in model it will be cleaner solution.
Create your own CustomeAttribute, for example:
[System.AttributeUsage(AttributeTargets.Property, AllowMultiple = false)]
public class MyCustomAttribute : System.Attribute
{
public MyCustomAttribute (string type)
{
MyType = type;
}
public string MyType { get; set; }
}
Then in model add it, like that:
public class MyModel
{
[MyCustom("word")]
public string Document { get; set; }
[MyCustom("time")]
public string Time { get; set; }
}
The last part is to create xml with this arguments.
You can do it likes that:
var doc = new XmlDocument();
MyModel myModel = new MyModel();//or get it from somewhere else
using (Stream s = new MemoryStream())
{
var settings = new XmlWriterSettings();
settings.Async = true;
settings.Indent = true;
var writer = XmlTextWriter.Create(s, settings);
await writer.WriteStartDocumentAsync();
await writer.WriteStartElementAsync(null,"Root", null);
myModel.GetType().GetProperties().ToList().ForEach(async p =>
{
dynamic value = p.GetValue(myModel);
writer.WriteStartElement(p.Name);
var myCustomAttribute = p.GetCustomAttributes(typeof(MyCustomAttribute), false).FirstOrDefault() as MyCustomAttribute;
if(myCustomAttribute != null)
{
await writer.WriteAttributeStringAsync(null, "MyType", null, myCustomAttribute.MyType );
}
writer.WriteValue(value);
await writer.WriteEndElementAsync();
});
await writer.WriteEndElementAsync();
await writer.FlushAsync();
s.Position = 0;
doc.Load(s);
writer.Close();
}
string myXml = doc.OuterXml
In myXml should be something like that:
(values are examples)
<?xml version="1.0" encoding="utf-8"?>
<Root>
<Document MyType="word">something</Document>
<Time MyType="time">11:31:29</Time>
</Root>
You can do it in other way, of course.
Here you have some docs which helped me:
https://learn.microsoft.com/en-us/dotnet/api/system.xml.xmlwriter?view=netframework-4.8#writing_elements

Related

How to generate an XML using XMLSerializer? [duplicate]

This question already has answers here:
Serialize an object to XML
(19 answers)
Closed 5 years ago.
I would like to generate an XML using XMLSerializer. I have an abstract Base class which is being inherited by other classes.
public abstract class Base
{
public string Name {get; set;}
public int ID {get; set;}
public Base(string Name, int ID)
{
this.Name = Name;
this.ID = ID;
}
}
public class HR: Base
{
public HR(string Name, int ID): Base(Name,ID)
{
}
}
public class IT : Base
{
public IT(string Name, int ID): Base(Name,ID)
{
}
}
I am not sure how to generate an XML of format
<Employee>
<HR>
<Name> </Name>
<ID> </ID>
</HR>
<IT>
<Name> </Name>
<ID> </ID>
</IT>
</Employee>
I apologise for the vague question. I have never used XMLSerializer before and not sure how to proceed with it. Any help would be greatly appreciated.
Thanks
As I read your xml, it seems you want to serialize a list of Employee.
I have a solution for you if your list is a member of a class (not directly serializing the list).
public abstract class Employee
{
public string Name { get; set; }
public int ID { get; set; }
public Employee(string Name, int ID)
{
this.Name = Name;
this.ID = ID;
}
}
public class HR : Employee
{
public HR() : base(null, 0) { } // default constructor is needed for serialization/deserialization
public HR(string Name, int ID) : base(Name, ID) { }
}
public class IT : Employee
{
public IT() : base(null, 0) { }
public IT(string Name, int ID) : base(Name, ID) { }
}
public class Group
{
[XmlArray("Employee")]
[XmlArrayItem("HR",typeof(HR))]
[XmlArrayItem("IT",typeof(IT))]
public List<Employee> list { get; set; }
public Group()
{
list = new List<Employee>();
}
}
class Program
{
static void Main(string[] args)
{
Group grp = new Group();
grp.list.Add(new HR("Name HR", 1));
grp.list.Add(new IT("Name IT", 2));
XmlSerializer ser = new XmlSerializer(typeof(Group));
ser.Serialize(Console.Out, grp);
}
}
And the output is :
<?xml version="1.0" encoding="ibm850"?>
<Group xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Employee>
<HR>
<Name>Name HR</Name>
<ID>1</ID>
</HR>
<IT>
<Name>Name IT</Name>
<ID>2</ID>
</IT>
</Employee>
</Group>
Very similar to your desired output, excepted one more element at the root "Group".
Deserialize with the same XmlSerializer(typeof(Group)) should work as well.
I think you need to use the XmlType attributes to make sure your elements show up as <HR> and <IT> instead of <employee xsi:type="HR">. Working demo below:
public abstract class Employee
{
public string Name { get; set; }
public string ID { get; set; }
public Employee(string Name, string ID)
{
this.Name = Name;
this.ID = ID;
}
}
public class HR : Employee
{
public HR(string Name, string ID) : base(Name, ID)
{
}
public HR() : base("No name", "No ID")
{
}
}
public class IT : Employee
{
public IT(string Name, string ID) : base(Name, ID)
{
}
public IT() : base("No name", "No ID")
{
}
}
I added default (parameter-less) constructors for the serializer.
Then you have to have some kind of wrapper object to handle a list of Employees:
public class Employees
{
[XmlElement(typeof(IT))]
[XmlElement(typeof(HR))]
public List<Employee> Employee { get; set; } //It doesn't really matter what this field is named, it takes the class name in the serialization
}
Next, you can use the serializer code from my comment to generate the XML:
var employees = new Employees
{
Employee = new List<Employee>()
{
new IT("Sugan", "88"),
new HR("Niels", "41")
}
};
var serializer = new XmlSerializer(typeof(Employees));
var xml = "";
using (var sw = new StringWriter())
{
using (XmlWriter writer = XmlWriter.Create(sw))
{
serializer.Serialize(writer, employees);
xml = sw.ToString();
}
}
Console.WriteLine(xml);
(Namespaces ommitted for clarity's sake)
This returns the following XML:
<?xml version="1.0" encoding="UTF-8"?>
<Employees xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<IT>
<Name>Sugan</Name>
<ID>88</ID>
</IT>
<HR>
<Name>Niels</Name>
<ID>41</ID>
</HR>
</Employees>
Add the [Serializable] Annotation to the class you want to serialize.
[System.Serializable]
public class Base
{
public string Name { get; set; }
public int ID { get; set; }
public Base(string Name, int ID)
{
this.Name = Name;
this.ID = ID;
}
}
To serialize in XML format, use the following code:
System.Xml.Serialization.XmlSerializer Serializer = new System.Xml.Serialization.XmlSerializer(typeof(Base));
Base Foo = new Base();
string xmldata = "";
using (var stringwriter = new System.IO.StringWriter())
{
using (System.Xml.XmlWriter xmlwriter = System.Xml.XmlWriter.Create(stringwriter))
{
Serializer.Serialize(xmlwriter, Foo);
xml = stringwriter.ToString(); // Your XML
}
}
To deserialize from XML back to your Base object, use the following code:
System.IO.MemoryStream FooStream = new System.IO.MemoryStream(System.Text.Encoding.UTF8.GetBytes(xml));
Base Foo;
Foo = (Base)Serializer.Deserialize(FooStream);

Serialize / Deserialize XML Derived From Treenode

I have two classes, "company" derived from Treenode, and "document".
[Serializable]
[XmlRoot("Company")]
public class Company : TreeNode, IXmlSerializable
{
private string _x;
private string _y;
public Company() { }
[XmlElement("X")]
public string X { get; set; }
[XmlElement("Y")]
public string Y { get; set; }
public System.Xml.Schema.XmlSchema GetSchema()
{
return null;
}
public void ReadXml(XmlReader reader)
{
if (reader.MoveToContent() == XmlNodeType.Element && reader.LocalName == "Company")
{
x = reader["X"].ToString;
y = reader["Y"].ToString;
}
}
public void WriteXml(XmlWriter writer)
{
writer.WriteElementString("X", this.X.ToString());
writer.WriteElementString("Y", this.Y.ToString());
}
}
public class Document
{
private int _id;
private string _name;
private Company _company;
public Document() { }
[XmlElement("ID")]
public int ID { get; set; }
[XmlElement("Name")]
public string Name { get; set; }
[XmlElement("Company")]
public Company Comp { get; set; }
}
When I try to serialize document, then save to file, its work. But when I deserialize, reader parameter always null. Any solutions ?
This is my code for deserialize. "sr" is variable that hold xml text.
var sr = new StreamReader(ms);
var myStr = sr.ReadToEnd();
XmlSerializer serializer = new XmlSerializer(typeof(List<Document>));
using (TextReader tr = new StringReader(myStr))
{
List<Document> docu = (List<Document>)serializer.Deserialize(tr);
}
I try to implement ISerialization and debug but never fired, and try to overide serialize and deserialize method, and no luck.
I am using .NET Framework 3.5
As explained in this article, implementing IXmlSerializable correctly is in fact quite tricky. Your implementation of ReadXml() appears to violate the requirement that it consume the wrapper element itself as well as all the contents, like so:
public void ReadXml(System.Xml.XmlReader reader)
{
reader.MoveToContent();
// Read attributes
Boolean isEmptyElement = reader.IsEmptyElement; // (1)
reader.ReadStartElement();
if (!isEmptyElement) // (1)
{
// Read Child elements X and Y
// Consume the end of the wrapper element
reader.ReadEndElement();
}
}
Furthermore, reader["X"] returns the value of the XML attribute named "X", as explained in the docs. In your WriteXml() you wrote the values of X and Y as nested XML elements. This explains the NullReferenceException. You need to fix your read and write methods to be consistent.
However, I'd suggest an alternative to implementing IXmlSerializable, which is to introduce a surrogate type for your Company. First, extract all the non-TreeNode properties of Company into an interface:
public interface ICompany
{
string X { get; set; }
string Y { get; set; }
}
public class Company : TreeNode, ICompany
{
public Company() { }
public string X { get; set; }
public string Y { get; set; }
}
This is optional but makes the code clearer. Next, introduce a surrogate POCO that implements the same interface but does not inherit from TreeNode:
public class CompanySurrogate : ICompany
{
public string X { get; set; }
public string Y { get; set; }
public static implicit operator CompanySurrogate(Company company)
{
if (company == null)
return null;
// For more complex types, use AutoMapper
return new CompanySurrogate { X = company.X, Y = company.Y };
}
public static implicit operator Company(CompanySurrogate surrogate)
{
if (surrogate == null)
return null;
// For more complex types, use AutoMapper
return new Company { X = surrogate.X, Y = surrogate.Y };
}
}
Notice that the surrogate can be implicitly converted to your original Company type? Now you can use the surrogate in XML serialization by setting the XmlElementAttribute.Type attribute property to be that of the surrogate:
public class Document
{
public Document() { }
[XmlElement("ID")]
public int ID { get; set; }
[XmlElement("Name")]
public string Name { get; set; }
[XmlElement("Company", Type = typeof(CompanySurrogate))]
public Company Comp { get; set; }
}
This avoids all possibilities of error in implementing IXmlSerializable. Given the following input list:
var list = new List<Document>
{
new Document { Name = "my name", ID = 101, Comp = new Company { X = "foo", Y = "bar", NodeFont = new System.Drawing.Font("Arial", 10) } },
new Document { Name = "2nd name", ID = 222, Comp = new Company { X = "tlon", Y = "ukbar" } },
};
The following XML can will be generated, and can be deserialized successfully:
<ArrayOfDocument xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Document>
<ID>101</ID>
<Name>my name</Name>
<Company>
<X>foo</X>
<Y>bar</Y>
</Company>
</Document>
<Document>
<ID>222</ID>
<Name>2nd name</Name>
<Company>
<X>tlon</X>
<Y>ukbar</Y>
</Company>
</Document>
</ArrayOfDocument>
That being said, I don't really recommend this design. Your UI should present your data model, it should not be your data model. See for instance How does one implement UI independent applications?. Replacing Company with ICompany whenever possible could be a first step to changing your design; you may find it becomes easier to replace your existing architecture with a TreeNode that looks like this:
public class CompanyNode : TreeNode
{
public ICompany Company { get; set; }
}

C# - XML serialization: omitting a certain element in my XML output

I have a weird XML setup here: I need to interface with a third-party and their XML layout that they're using is beyond my control - no chance to changing anything...
In the scope of a larger XML, I find myself needing to serialize (and later also deserialize) a list of items (for a mobile device) which are defined as having a Type and a Number property (both strings). So this would be something like:
public class SerialNumber
{
public string Type { get; set; }
public string Number { get; set; }
}
And this would normally serialize a List<SerialNumber> SerialNumbers as
<SerialNumbers>
<SerialNumber>
<Type>SN</Type>
<Number>CBS583ABC123</Number>
</SerialNumber>
<SerialNumber>
<Type>IMEI</Type>
<Number>35-924106-659945-4</Number>
</SerialNumber>
</SerialNumbers>
However, in my case, I need to send this XML:
<SerialNumbers>
<Type>SN</Type>
<Number>CBS583ABC123</Number>
<Type>IMEI</Type>
<Number>35-924106-659945-4</Number>
</SerialNumbers>
So basically, the list elements need to be omitted - I just need a container <SerialNumbers> and then for each entry in the list, I only need to serialize out the Type and Number subelements.
How can I do this easily in .NET with the XmlSerializer ?
I tried to use
[XmlRoot(ElementName="")]
public class SerialNumber
or
[XmlArray]
[XmlArrayItem(ElementName = "")]
public List<SerialNumber> SerialNumbers { get; set; }
but neither of these worked - I still get my full serialization with the <SerialNumber> elements inside the <SerialNumbers> container...
Is there an easy trick to achieve what I'm looking for? I'd much rather not go low-level and start concetanating together my XML manually....
Thanks!
You could use custom serialization with IXmlSerializable.
public class SerialNumbers : List<SerialNumber>, IXmlSerializable
{
public XmlSchema GetSchema()
{
return null;
}
public void ReadXml(XmlReader reader)
{
Clear();
reader.ReadStartElement();
while (reader.NodeType != XmlNodeType.EndElement)
{
var serialNumber = new SerialNumber
{
Type = reader.ReadElementContentAsString("Type", ""),
Number = reader.ReadElementContentAsString("Number", "")
};
Add(serialNumber);
}
reader.ReadEndElement();
}
public void WriteXml(XmlWriter writer)
{
foreach (var serialNumber in this)
{
writer.WriteElementString("Type", serialNumber.Type);
writer.WriteElementString("Number", serialNumber.Number);
}
}
}
public class SerialNumber
{
public string Type { get; set; }
public string Number { get; set; }
}
Example:
var ser = new XmlSerializer(typeof(SerialNumbers));
var reader = new StringReader(#"
<SerialNumbers>
<Type>SN</Type>
<Number>CBS583ABC123</Number>
<Type>IMEI</Type>
<Number>35-924106-659945-4</Number>
</SerialNumbers>
".Trim());
var result = (SerialNumbers) ser.Deserialize(reader);
var writer = new StringWriter();
ser.Serialize(writer, result);
Result:
<?xml version="1.0" encoding="utf-16"?>
<SerialNumbers>
<Type>SN</Type>
<Number>CBS583ABC123</Number>
<Type>IMEI</Type>
<Number>35-924106-659945-4</Number>
</SerialNumbers>
This might do the trick for you
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
[System.Xml.Serialization.XmlRootAttribute(Namespace = "", IsNullable = false)]
public partial class SerialNumbers
{
private string[] itemsField;
private ItemsChoiceType[] itemsElementNameField;
[System.Xml.Serialization.XmlElementAttribute("Number", typeof(string))]
[System.Xml.Serialization.XmlElementAttribute("Type", typeof(string))]
[System.Xml.Serialization.XmlChoiceIdentifierAttribute("ItemsElementName")]
public string[] Items
{
get
{
return this.itemsField;
}
set
{
this.itemsField = value;
}
}
[System.Xml.Serialization.XmlElementAttribute("ItemsElementName")]
[System.Xml.Serialization.XmlIgnoreAttribute()]
public ItemsChoiceType[] ItemsElementName
{
get
{
return this.itemsElementNameField;
}
set
{
this.itemsElementNameField = value;
}
}
}
[System.Xml.Serialization.XmlTypeAttribute(IncludeInSchema = false)]
public enum ItemsChoiceType
{
Number,
Type,
}

How do I make the method/s generic which returns different types, but accepts the same type of instance?

I have multiple methods which reads data from XML having the following format:
<?xml version = "1.0" encoding="UTF-8" standalone="yes"?>
<document>
<employee>
<name>
<lastname>Sample</lastname>
<firstname>Test</firstname>
</name>
<professionalDetails>
<hiredate>October 15, 2016</hiredate>
<designation>Clerk</designation>
</professionalDetails>
<projects>
<project>
<product>Printer</product>
<id>111</id>
<price>$111.00</price>
</project>
<project>
<product>Laptop</product>
<id>222</id>
<price>$989.00</price>
</project>
</projects>
</employee>
</document>
To read the above data, I have the following methods with their respective classes.
Please note that I have my own implementation of "GetElementAsString" method. Bear with me for not providing the implementation of that.
Methods:
private static NameDetails GetsNameDetails(XNode content)
{
var element = content.XPathSelectElement("document/employee/name");
return new NameDetails
{
FirstName = element.GetElementAsString("firstName"),
LastName = element.GetElementAsString("lastName")
};
}
private static ProfessionalDetails GetsProfessionalDetailsDetails(XNode content)
{
var element = content.XPathSelectElement("document/employee/professionalDetails");
return new ProfessionalDetails
{
HireDate = element.GetElementAsString("hiredate"),
Designation = element.GetElementAsString("designation")
};
}
private static Projects GetsProjectDetails(XNode content)
{
var element = content.XPathSelectElement("document/employee/projects/project");
return new Projects
{
Id = element.GetElementAsString("id"),
Price = element.GetElementAsString("price"),
Product = element.GetElementAsString("product")
};
}
}
internal class Projects
{
public int Id { get; set; }
public string Product { get; set; }
public string Price { get; set; }
}
internal class ProfessionalDetails
{
public DateTime HireDate { get; set; }
public string Designation { get; set; }
}
internal class NameDetails
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
The underlying logic is the same for both methods. The initializing type is the only thing that gets changed. The return value of the method and the properties/fields to be initialized change, but the parameter remains the same.
How do I have one single Generic method for the below methods and decide the type to be initialised at run-time?
You could write something like this:
private static T ThingFiller<T>(
XNode context,
string elementStr,
params Action<Func<string, string>, T>[] setters
)
where T : new()
{
var element = context.XPathSelectElement(elementStr);
var t = new T();
foreach (var setter in setters)
setter(element.GetElementAsString, t);
return t;
}
private static NameDetails GetsNameDetails(XNode content)
{
return ThingFiller<NameDetails>(content, "document/employee/name",
(func, nd) => nd.FirstName = func("firstName"),
(func, nd) => nd.LastName = func("lastName")
);
}
Alternatively, you could use an XML library and simply define how to fill the fields via attributes and mapping.
You could add a generic type and then depending on the type decide how you want to parse the node:
private static T GetsDetails<T>(XNode content)
{
if(typeof(T) == typeof(ProjectDetails)){
var element = content.XPathSelectElement("document/employee/projects/project");
return (T)new Projects
{
Id = element.GetElementAsString("id"),
Price = element.GetElementAsString("price"),
Product = element.GetElementAsString("product")
};
}
else if(typeof(T) == typeof(ProfessionalDetails){ ... }
else if (...) {...}
}
I wouldn't recommend this approach though: you still have to do type-checking and you gain very little. The initial implementation you have is far simpler.
You could create an attribute which determines which XPath expression should be used. Example:
[XPathSelector("document/employee/projects/project")]
internal class Projects
{
public int Id { get; set; }
public string Product { get; set; }
public string Price { get; set; }
}
and then you could use this via reflection (code is untested, no c# compiler available here):
private static T GetNode<T>(XNode content)
: where T : new()
{
var selector = typeof(T).GetCustomProperty<XPathSelector>();
var element = content.XPathSelectElement(selector.XPathSelector);
var ret = new T();
foreach (var child in element.Elements) {
var property = typeof(T).GetProperties().Single(p => p.Name.ToLower() == child.Name.ToLower());
property.SetValue(ret, child.GetElementAsString(child.Name));
}
return ret;
}

Override a property to another type on derived class

I'm trying to find out a solution for this, but I'm not sure if it's possible or not.
I have a base class, lets say
public class A
{
[XmlAttribute("Date")]
public DateTime Date {get;set;}
}
and a derived class:
public class B: A
{
[XmlAttribute("Date")]
public new String StringDate {get;set;}
}
I have to serialize a Xml.
The value of "Date" on the Xml, is String and in fact it's not a DateTime format string. But I use "A" for many other stuff so I cannot just change it to String without affecting other parts of the program. Sadly it is not an option.
So my idea is to create a derived class "B" who inherit everything of "A" and overrided the property Date to get it fill from the deserialization and then format it to DateTime.
I read about virtual or abstracts but I'm not acquainted with it and don't have any clue about it, if it is the solution maybe someone can guide me on the first steps.
Anyone can help me?
EDIT
XML:
<Vorgang Vorgang="HQHT8GTQ">
<Vertragsbeginn Vertragsbeginn="20140202" />
</Vorgang>
Class A:
[DataContract(Name = "Vorgang")]
[KnownType(typeof(Vorgang))]
public class Vorgang
{
[IgnoreDataMember]
public DateTime Vertragsbeginn { get; set; }
}
Class B:
public class VorgangOverride : UTILMD.Vorgang
{
private string datestring;
[XmlAttribute("Vertragsbeginn")]
public new String Vertragsbeginn {
get { return datestring; }
set
{
base.Vertragsbeginn = DateUtil.StringToDate(value, EDIEnums.Vertragsbeginn);
datestring = value;
}
}
}
Deserialization method:
private static VorgangOverride Deserialize (XmlNode inVorgang)
{
using (MemoryStream stm = new MemoryStream())
{
using (StreamWriter stw = new StreamWriter(stm))
{
stw.Write(inVorgang.OuterXml);
stw.Flush();
stm.Position = 0;
XmlRootAttribute xRoot = new XmlRootAttribute { ElementName = "Vorgang", IsNullable = true };
var serializer = new XmlSerializer(typeof(VorgangOverride), xRoot);
VorgangOverride podItem = (VorgangOverride) serializer.Deserialize(stm);
return podItem;
}
}
}
EDIT:
Solved using
[XmlRoot("Vorgang")]
public class VorgangOverride
{
public VorgangOverride()
{
}
#region Public Properties
public string datestring;
[XmlElement("Vertragsbeginn")]
public Vertragsbeginn VertragsbeginnAsString { get ; set ;}
#endregion
}
public class Vertragsbeginn
{
[XmlAttribute("Vertragsbeginn")]
public String vertragsbeginn { get; set; }
}
I found the solution:
[DataContract(Name = "Vorgang")]
[KnownType(typeof(Vorgang))]
public class Vorgang
{
[XmlIgnore] // use XmlIgnore instead IgnoreDataMember
public DateTime Vertragsbeginn { get; set; }
}
// this class map all elements from the xml that you show
[XmlRoot("Vorgang")] // to map the Xml Vorgang as a VorgangOverride instance
public class VorgangOverride : Vorgang
{
[XmlAttribute("Vorgang2")] // to map the Vorgang attribute
public string VorgangAttribute { get; set; }
[XmlElement(ElementName = "Vertragsbeginn")] // to map the Vertragsbeginn element
public Vertragsbeginn VertragsbeginnElement
{
get { return _vertragsbeginn; }
set
{
base.Vertragsbeginn = new DateTime(); // here I Assing the correct value to the DateTime property on Vorgan class.
_vertragsbeginn = value;
}
}
private Vertragsbeginn _vertragsbeginn;
}
// this class is used to map the Vertragsbeginn element
public class Vertragsbeginn
{
[XmlAttribute("Vertragsbeginn")] // to map the Vertragsbeginn attriubute on the Vertragsbeginn element
public string VertragsbeginnAttribute { get; set; }
}
later I say:
var string xmlContent =
#"<Vorgang Vorgang2=""HQHT8GTQ"">
<Vertragsbeginn Vertragsbeginn=""20140202"" />
</Vorgang>";
var a = Deserialize<VorgangOverride>(xmlContent);
and this is the method to Deserialize:
// method used to deserialize an xml to object
public static T Deserialize<T>(string xmlContent)
{
T result;
var xmlSerializer = new XmlSerializer(typeof(T));
using (TextReader textReader = new StringReader(xmlContent))
{
result = ((T)xmlSerializer.Deserialize(textReader));
}
return result;
}
You will not be able to override a property with an other class type.
The reason is Polymorphism. (more information: https://msdn.microsoft.com/en-us/library/ms173152.aspx)
You can cast the class B to class A. Which means the class B must have all the properties and methods class A has, too. But in your case class B would have a String rather than a Date called Date. Which is simply not possible.

Categories