If I have the following:
public class A
{
public B b {get;set;}
}
public class B
{
public string Name {get;set;}
public string Address {get;set;
}
what I want is the xml as:
<A Name="some data" Address="address..." />
So I am trying to flatten my referenced object as attributes.
Is this possible with an XmlSerializer?
yeah, you can do this by using the IXmlSerializable interface:
[Serializable]
public class MyClass : IXmlSerializable
{
public MySubClass SubClass { get; set; }
public XmlSchema GetSchema()
{
return null;
}
public void ReadXml(XmlReader reader)
{
throw new NotImplementedException();
}
public void WriteXml(XmlWriter writer)
{
writer.WriteStartAttribute("Name");
writer.WriteString(SubClass.Name);
writer.WriteEndAttribute();
writer.WriteStartAttribute("Phone");
writer.WriteString(SubClass.Phone);
writer.WriteEndAttribute();
}
}
[Serializable]
public class MySubClass
{
public string Name { get; set; }
public string Phone { get; set; }
}
and then call it like this
var serializer = new XmlSerializer(typeof(MyClass));
using (var writer = new StringWriter())
{
var myClass = new MyClass() {SubClass = new MySubClass() {Name = "Test", Phone = "1234"}};
serializer.Serialize(writer, myClass);
string xml = writer.ToString();
}
this is the xml result:
<?xml version="1.0" encoding="utf-16"?>
<MyClass Name="Test" Phone="1234" />
see msdn too: http://msdn.microsoft.com/en-us/library/system.xml.serialization.ixmlserializable.aspx
or you could just specify the attributes that #Morpheus named ;)
Related
I need class which takes two parameter
1- Type ==> class name
2- xml string ==> xml document in string format.
now following class convert xml to object which is all working fine but I need final version as generic type
Converter class
public static partial class XMLPrasing
{
public static Object ObjectToXML(string xml, Type objectType)
{
StringReader strReader = null;
XmlSerializer serializer = null;
XmlTextReader xmlReader = null;
Object obj = null;
try
{
strReader = new StringReader(xml);
serializer = new XmlSerializer(objectType);
xmlReader = new XmlTextReader(strReader);
obj = serializer.Deserialize(xmlReader);
}
catch (Exception exp)
{
//Handle Exception Code
var s = "d";
}
finally
{
if (xmlReader != null)
{
xmlReader.Close();
}
if (strReader != null)
{
strReader.Close();
}
}
return obj;
}
}
as Example class
[Serializable]
[XmlRoot("Genders")]
public class Gender
{
[XmlElement("Genders")]
public List<GenderListWrap> GenderListWrap = new List<GenderListWrap>();
}
public class GenderListWrap
{
[XmlAttribute("list")]
public string ListTag { get; set; }
[XmlElement("Item")]
public List<Item> GenderList = new List<Item>();
}
public class Item
{
[XmlElement("CODE")]
public string Code { get; set; }
[XmlElement("DESCRIPTION")]
public string Description { get; set; }
}
//
<Genders><Genders list=\"1\">
<Item>
<CODE>M</CODE>
<DESCRIPTION>Male</DESCRIPTION></Item>
<Item>
<CODE>F</CODE>
<DESCRIPTION>Female</DESCRIPTION>
</Item></Genders>
</Genders>
Please check my solution if it will help you.
Below is Method, which converts xml to generic Class.
public static T GetValue<T>(String value)
{
StringReader strReader = null;
XmlSerializer serializer = null;
XmlTextReader xmlReader = null;
Object obj = null;
try
{
strReader = new StringReader(value);
serializer = new XmlSerializer(typeof(T));
xmlReader = new XmlTextReader(strReader);
obj = serializer.Deserialize(xmlReader);
}
catch (Exception exp)
{
}
finally
{
if (xmlReader != null)
{
xmlReader.Close();
}
if (strReader != null)
{
strReader.Close();
}
}
return (T)Convert.ChangeType(obj, typeof(T));
}
How to call that method :
Req objreq = new Req();
objreq = GetValue(strXmlData);
Req is Generic Class . strXmlData is xml string .
Request sample xml :
<?xml version="1.0"?>
<Req>
<book id="bk101">
<author>Gambardella, Matthew</author>
<title>XML Developer's Guide</title>
<genre>Computer</genre>
<price>44.95</price>
<publish_date>2000-10-01</publish_date>
<description>An in-depth look at creating applications
with XML.</description>
</book>
<book id="bk102">
<author>Ralls, Kim</author>
<title>Midnight Rain</title>
<genre>Fantasy</genre>
<price>5.95</price>
<publish_date>2000-12-16</publish_date>
<description>A former architect battles corporate zombies,
an evil sorceress, and her own childhood to become queen
of the world.</description>
</book>
</Req>
Request Class :
[System.SerializableAttribute()]
public partial class Req {
[System.Xml.Serialization.XmlElementAttribute("book")]
public catalogBook[] book { get; set; }
}
[System.SerializableAttribute()]
public partial class catalogBook {
public string author { get; set; }
public string title { get; set; }
public string genre { get; set; }
public decimal price { get; set; }
public System.DateTime publish_date { get; set; }
public string description { get; set; }
public string id { get; set; }
}
In my case it is working perfectly ,hope it will work in your example .
Thanks .
If you want to serialize and deserialize an object with xml this is the easiest way:
The class we want to serialize and deserialize:
[Serializable]
public class Person()
{
public int Id {get;set;}
public string Name {get;set;}
public DateTime Birth {get;set;}
}
Save an object to xml:
public static void SaveObjectToXml<T>(T obj, string file) where T : class, new()
{
if (string.IsNullOrWhiteSpace(file))
throw new ArgumentNullException("File is empty");
var serializer = new XmlSerializer(typeof(T));
using (Stream fileStream = new FileStream(file, FileMode.Create))
{
using (XmlWriter xmlWriter = new XmlTextWriter(file, Encoding.UTF8))
{
serializer.Serialize(xmlWriter, obj);
}
}
}
Load an object from xml:
public static T LoadObjectFromXml<T>(string file) where T : class, new()
{
if (string.IsNullOrWhiteSpace(file))
throw new ArgumentNullException("File is empty");
if (File.Exists(file))
{
XmlSerializer deserializer = new XmlSerializer(typeof(T));
using (TextReader reader = new StreamReader(file))
{
obj = deserializer.Deserialize(reader) as T;
}
}
}
How to use this methods with our Person class:
Person testPerson = new Person {Id = 1, Name="TestPerson", Birth = DateTime.Now};
SaveObjectToXml(testPerson, string "C:\\MyFolder");
//Do some other stuff
//Oh now we need to load the object
var myPerson = LoadObjectFromXml<Person>("C:\\MyFolder");
Console.WriteLine(myPerson.Name); //TestPerson
The Save and Load Methods are working with every object which class is [Serializable] and which contains public empty constructor.
I have a class has a property need to be serialized with some specified type.
[Serializable]
public class MyClass
{
private object _data;
//[Any magic attribute here to exclude some types while serialization?]
public object Data
{
get { return _data;}
set { _data = value; }
}
}
[Serializable]
public class A
{}
[Serializable]
public class B
{}
MyClass myClass = new MyClass();
In some cases I have:
myClass.Data = A;
In some cases I have:
myClass.Data = B;
And then I do serialization for MyClass.
My question is: how can I serialize class B but class A as Data property inside MyClass?
Thank you for helping me!
You are looking for the ShouldSerialize Pattern:
[XmlRoot(ElementName="Foo")]
public class Foo
{
[XmlElement(ElementName="Bar")]
public int Bar { get; set; }
public bool ShouldSerializeBar()
{
return (Bar > 10);
}
}
The property 'Bar' will be serialized if it's greater than 10, otherwise, it won't.
Just create a boolean method with 'ShouldSerialize' in front of your property name. If the boolean then returns false, the property wil not be serialized.
More specific to your situation:
[XmlInclude(typeof(Foo))]
[XmlInclude(typeof(Bar))]
[XmlRoot(ElementName = "Foo")]
public class FooBar
{
[XmlElement(ElementName = "Data")]
public object Data { get; set; }
public bool ShouldSerializeData()
{
return (Data.GetType() == typeof(Foo));
}
}
[XmlRoot(ElementName="Foo")]
public class Foo
{
[XmlElement(ElementName="Bar")]
public int Bar { get; set; }
}
[XmlRoot(ElementName = "Bar")]
public class Bar
{
[XmlElement(ElementName = "Foo")]
public int Foo { get; set; }
}
Try
[XmlIgnore] attribute class
namespace System.Xml.Serialization
use XmlSerializer Class to serialize
I think that you are looking for this - http://msdn.microsoft.com/en-us/library/system.xml.serialization.xmlattributes.xmlignore(v=vs.110).aspx
You can add [XmlIgnoreAttribute] attributte to your Data property, and optionally (if (Data is B) ..) remove it with newly created XmlAttributes. Then you use new XmlSerializer with edited behaviour.
Edit: Example:
public class A
{
public string Text { get; set; }
}
public class B : A { }
public class C : A { }
[XmlInclude(typeof(B))]
[XmlInclude(typeof(C))]
public class D
{
public object Data { get; set; }
public string Test = "Test";
}
class Program
{
static void Main(string[] args)
{
var d = new D();
d.Data = new B() { Text = "Data" };
var xSer = CreateOverrider(d);
xSer.Serialize(new StreamWriter(File.OpenWrite("D:\\testB.xml")), d);
}
public static XmlSerializer CreateOverrider(D d)
{
XmlAttributeOverrides xOver = new XmlAttributeOverrides();
XmlAttributes attrs = new XmlAttributes();
attrs.XmlIgnore = d.Data is B;
xOver.Add(typeof(D), "Data", attrs);
XmlSerializer xSer = new XmlSerializer(typeof(D), xOver);
return xSer;
}
}
For B you get:
<?xml version="1.0" encoding="utf-8"?>
<D xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Test>Test</Test>
</D>
For C:
<?xml version="1.0" encoding="utf-8"?>
<D xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Test>Test</Test>
<Data xsi:type="C">
<Text>Data</Text>
</Data>
</D>
I have this existing XML file serving as a template with NO data, just simple nodes... here's a sample:
<?xml version="1.0" encoding="utf-8" ?>
<catalog>
<cd>
<title />
<artist />
<country />
<company />
<price />
<year />
</cd>
</catalog>
Now I have created a similar class for it.
public class Cd
{
public string Title { get; set; }
public string Artist { get; set; }
public string Country { get; set; }
public string Company { get; set; }
public string Price { get; set; }
public string Year { get; set; }
}
The purpose is this:
Put values on the properties of the var cd = new Cd(); object
Get the existing XML file (template) then pass the values in it (like mapping the object to the existing XML)
Transform the XML template(with values) into XSLT to become HTML
I think that's all.
How to properly do this?
Thanks a lot!
You can use serialization to achieve (1) and (2)
[Serializable]
public class Cd
{
public string Title { get; set; }
public string Artist { get; set; }
public string Country { get; set; }
public string Company { get; set; }
public string Price { get; set; }
public string Year { get; set; }
}
now in order to create an xml from an object use:
public static string SerializeObject<T>(this T obj)
{
var ms = new MemoryStream();
var xs = new XmlSerializer(obj.GetType());
var xmlTextWriter = new XmlTextWriter(ms, Encoding.UTF8);
xs.Serialize(xmlTextWriter, obj);
string serializedObject = new UTF8Encoding().GetString((((MemoryStream)xmlTextWriter.BaseStream).ToArray()));
return serializedObject;
}
in order to create an object from XML use:
public static T DeserializeObject<T>(this string xml)
{
if (xml == null)
throw new ArgumentNullException("xml");
var xs = new XmlSerializer(typeof(T));
var ms = new MemoryStream(new UTF8Encoding().GetBytes(xml));
try
{
new XmlTextWriter(ms, Encoding.UTF8);
return (T)xs.Deserialize(ms);
}
catch
{
return default(T);
}
finally
{
ms.Close();
}
}
I would create class:
class catalog
{
public CD cd {get;set;}
}
Here is serialization and deserealization helper:
public class Xml
{
public static string Serialize<T>(T value) where T : class
{
if (value == null)
{
return string.Empty;
}
var xmlSerializer = new XmlSerializer(typeof(T));
var stringWriter = new StringWriter();
using (var xmlWriter = XmlWriter.Create(stringWriter))
{
xmlSerializer.Serialize(xmlWriter, value);
return stringWriter.ToString();
}
}
public static T Deserialize<T>(string xml)
{
var serializer = new XmlSerializer(typeof(T));
T result;
using (TextReader reader = new StringReader(xml))
{
result = (T) serializer.Deserialize(reader);
}
return result;
}
}
Simply call:
catalog catalogObject = Xml.Deserialize<catalog>(xmlCatalogString);
I suspect you also will need to put some attributes on properties like XmlElement(ElementName = "title") because it is case sensitive.
MSDN
I have a class named Node and inside that i have Property of Type Document Class.
When I serialize it into XML, I get the output as
<Node>
<DocumentType>
<File></File>
</DoumentType>
<Node>
But I want the output as
<Node>
<File></File>
<Node>
Object Code
public class Document
{
[XmlElement(ElementName = "file")]
public string File { get; set; }
}
public class Node
{
public Document NodeDocument
{
get;
set;
}
}
How can I do that using C# xml Serialization?
Following Kami's suggestion, here is the code for your reference. All credit goes to Kami.
public class Node : IXmlSerializable {
public Node() {
NodeDocument = new Document();
}
public Document NodeDocument { get; set; }
public System.Xml.Schema.XmlSchema GetSchema() {
return null;
}
public void ReadXml(XmlReader reader) {
reader.ReadStartElement();
NodeDocument.File = reader.ReadString();
reader.ReadEndElement();
}
public void WriteXml(XmlWriter writer) {
writer.WriteStartElement("file");
writer.WriteString(NodeDocument.File);
writer.WriteEndElement();
}
}
public class Document {
public String File { get; set; }
}
class Program {
static void Main(string[] args) {
var node = new Node();
node.NodeDocument.File = "bbb.txt";
Serialize<Node>("a.xml", node);
node = Deserialize<Node>("a.xml");
Console.WriteLine(node.NodeDocument.File);
Console.Read();
}
static T Deserialize<T>(String xmlFilePath) where T : class {
using (var textReader = File.OpenText(xmlFilePath)) {
using (var xmlTextReader = new XmlTextReader(textReader)) {
var serializer = new XmlSerializer(typeof(T));
return (T)serializer.Deserialize(xmlTextReader);
}
}
}
static void Serialize<T>(String xmlFilePath, T obj) where T : class {
using (var textWriter = File.CreateText(xmlFilePath)) {
using (var xmlTextWriter = new XmlTextWriter(textWriter)) {
var serializer = new XmlSerializer(typeof(T));
serializer.Serialize(xmlTextWriter, obj);
}
}
}
}
Have you considered implementing IXmlSerializable interface - http://msdn.microsoft.com/en-us/library/system.xml.serialization.ixmlserializable.aspx.
You should then be able to write custom serialization/deserialization to facilitate the above.
I'm trying to serialize an object to meet another systems requirements.
It need to look like this:
<custom-attribute name="Colour" dt:dt="string">blue</custom-attribute>
but instead is looking like this:
<custom-attribute>blue</custom-attribute>
So far I have this:
[XmlElement("custom-attribute")]
public String Colour{ get; set; }
I'm not really sure what metadata I need to achieve this.
You could implement IXmlSerializable:
public class Root
{
[XmlElement("custom-attribute")]
public Colour Colour { get; set; }
}
public class Colour : IXmlSerializable
{
[XmlText]
public string Value { get; set; }
public XmlSchema GetSchema()
{
return null;
}
public void ReadXml(XmlReader reader)
{
throw new NotImplementedException();
}
public void WriteXml(XmlWriter writer)
{
writer.WriteAttributeString("dt:dt", "", "string");
writer.WriteAttributeString("name", "Colour");
writer.WriteString(Value);
}
}
class Program
{
static void Main()
{
var serializer = new XmlSerializer(typeof(Root));
var root = new Root
{
Colour = new Colour
{
Value = "blue"
}
};
serializer.Serialize(Console.Out, root);
}
}