Serialize Property as Xml Attribute in Element
You will need wrapper classes:
public class SomeIntInfo
{
[XmlAttribute]
public int Value { get; set; }
}
public class SomeStringInfo
{
[XmlAttribute]
public string Value { get; set; }
}
public class SomeModel
{
[XmlElement("SomeStringElementName")]
public SomeStringInfo SomeString { get; set; }
[XmlElement("SomeInfoElementName")]
public SomeIntInfo SomeInfo { get; set; }
}
or a more generic approach if you prefer:
public class SomeInfo<T>
{
[XmlAttribute]
public T Value { get; set; }
}
public class SomeModel
{
[XmlElement("SomeStringElementName")]
public SomeInfo<string> SomeString { get; set; }
[XmlElement("SomeInfoElementName")]
public SomeInfo<int> SomeInfo { get; set; }
}
And then:
class Program
{
static void Main()
{
var model = new SomeModel
{
SomeString = new SomeInfo<string> { Value = "testData" },
SomeInfo = new SomeInfo<int> { Value = 5 }
};
var serializer = new XmlSerializer(model.GetType());
serializer.Serialize(Console.Out, model);
}
}
will produce:
<?xml version="1.0" encoding="ibm850"?>
<SomeModel xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<SomeStringElementName Value="testData" />
<SomeInfoElementName Value="5" />
</SomeModel>
Serialize Property as Xml Attribute in new Element
It seems you have to convert your xml to custom format so you have to implement IXmlSerializable
interface in your Person
class object like.
public class Person : IXmlSerializable
{
public int Id { get; set; }
public string Name { get; set; }
public Address Address { get; set; }
public XmlSchema GetSchema() { throw new NotImplementedException(); }
public void ReadXml(XmlReader reader)
{
while (reader.Read())
{
if (reader.Name == "attr" && reader.GetAttribute("n") == "id")
Id = Convert.ToInt32(reader.ReadInnerXml());
if (reader.Name == "attr" && reader.GetAttribute("n") == "name")
Name = reader.ReadInnerXml();
if (reader.Name == "attr" && reader.GetAttribute("n") == "street")
Address = new Address { Street = reader.ReadInnerXml() };
}
}
public void WriteXml(XmlWriter writer)
{
//Start "struct"
writer.WriteStartElement("struct");
writer.WriteAttributeString("n", "People");
writer.WriteStartElement("attr");
writer.WriteAttributeString("n", "id");
writer.WriteString(Id.ToString());
writer.WriteEndElement();
writer.WriteStartElement("attr");
writer.WriteAttributeString("n", "name");
writer.WriteString(Name.ToString());
writer.WriteEndElement();
//Start inner "struct"
writer.WriteStartElement("struct");
writer.WriteAttributeString("n", "Address");
writer.WriteStartElement("attr");
writer.WriteAttributeString("n", "street");
writer.WriteString(Address.Street.ToString());
writer.WriteEndElement();
//End inner "struct"
writer.WriteEndElement();
//End "struct"
writer.WriteEndElement();
}
}
And you can serialize and deserialize your xml like.
Person person = new Person
{
Id = 2,
Name = "FIO FIO IFO",
Address = new Address { Street = "Golden Gate" }
};
//--------------------Serialization----------------------------
XmlSerializer serializer = new XmlSerializer(person.GetType());
using (StreamWriter writer = new StreamWriter(@"Path to xml file"))
{
serializer.Serialize(writer, person);
}
//--------------------Deserialization----------------------------
using (StringReader stringReader = new StringReader(File.ReadAllText(@"Path to same xml file that generated by above serializer")))
{
person = (Person)serializer.Deserialize(stringReader);
Console.WriteLine("Id: " + person.Id);
Console.WriteLine("Name: " + person.Name);
Console.WriteLine("Street: " + person.Address.Street);
Console.ReadLine();
}
Output for Serialization:
Output for Deserialization:
Alternative
You can also create a custom methods to read and write xml.
1) Write
public static void WriteXml(Person person, string path)
{
using (XmlWriter writer = XmlWriter.Create(path))
{
//Start "struct"
writer.WriteStartElement("struct");
writer.WriteAttributeString("n", "People");
writer.WriteStartElement("attr");
writer.WriteAttributeString("n", "id");
writer.WriteString(person.Id.ToString());
writer.WriteEndElement();
writer.WriteStartElement("attr");
writer.WriteAttributeString("n", "name");
writer.WriteString(person.Name.ToString());
writer.WriteEndElement();
//Start inner "struct"
writer.WriteStartElement("struct");
writer.WriteAttributeString("n", "Address");
writer.WriteStartElement("attr");
writer.WriteAttributeString("n", "street");
writer.WriteString(person.Address.Street.ToString());
writer.WriteEndElement();
//End inner "struct"
writer.WriteEndElement();
//End "struct"
writer.WriteEndElement();
}
}
Usage:
Person person = new Person
{
Id = 2,
Name = "FIO FIO IFO",
Address = new Address { Street = "Golden Gate" }
};
WriteXml(person, @"Path to xml file");
2) Read
public static Person ReadXml(string path)
{
Person person = new Person();
using (XmlReader reader = XmlReader.Create(path))
{
while (reader.Read())
{
if (reader.Name == "attr" && reader.GetAttribute("n") == "id")
person.Id = Convert.ToInt32(reader.ReadInnerXml());
if (reader.Name == "attr" && reader.GetAttribute("n") == "name")
person.Name = reader.ReadInnerXml();
if (reader.Name == "attr" && reader.GetAttribute("n") == "street")
person.Address = new Address { Street = reader.ReadInnerXml() };
}
}
return person;
}
Usage:
Person result = ReadXml(@"Path to same xml file that generated by above serializer");
How to serialize object's property to XML element's attribute?
What you need is a property for the string representation that gets serialized:
[Serializable]
public class ProgramInfo
{
[XmlAttribute]
public string Name { get; set; }
[XmlIgnore]
public Version Version { get; set; }
[XmlAttribute("Version")
public string VersionString
{
get { return this.Version.ToString(); }
set{ this.Version = Parse(value);}
}
}
XML serialisation for class properties with additional meta data
You can use XElement
from System.Xml.Linq
to achieve this. As your data is static you can assign them easily. Sample code below -
XElement data= new XElement("Vehicle",
new XElement("VehicleId", new XAttribute("AppliesTo", "C1"),"1244"),
new XElement("Make", new XAttribute("AppliesTo", "Common"), "HXV"),
new XElement("Model", new XAttribute("AppliesTo", "C2"), "34 - 34")
);
//OUTPUT
<Vehicle>
<VehicleId AppliesTo="C1">1244</VehicleId>
<Make AppliesTo="Common">HXV</Make>
<Model AppliesTo="C2">34 - 34</Model>
</Vehicle>
If you are not interested in System.Xml.Linq
then you have another option of XmlSerializer
class. For that you need yo define separate classes for each property of vehicle
. Below is the sample code and you can extend the same for Make and Model
-
[XmlRoot(ElementName = "VehicleId")]
public class VehicleId
{
[XmlAttribute(AttributeName = "AppliesTo")]
public string AppliesTo { get; set; }
[XmlText]
public string Text { get; set; }
}
[XmlRoot(ElementName = "Vehicle")]
public class Vehicle
{
[XmlElement(ElementName = "VehicleId")]
public VehicleId VehicleId { get; set; }
//Add other properties here
}
Then create test data and use XmlSerializer
class to construct XML -
Vehicle vehicle = new Vehicle
{
VehicleId = new VehicleId
{
Text = "1244",
AppliesTo = "C1",
}
};
XmlSerializer testData = new XmlSerializer(typeof(Vehicle));
var xml = "";
using (var sww = new StringWriter())
{
using (XmlWriter writer = XmlWriter.Create(sww))
{
testData.Serialize(writer, vehicle);
xml = sww.ToString(); // XML
}
}
Is there a way to retain XML Attributes when serializing part of a class?
is there a way to specify tag names when serializing a simple List.
In general, depending on the exact scenario, it may be possible to get this to work. See MSDN's How to: Specify an Alternate Element Name for an XML Stream. The example there involves overriding serialization of a specific field, but it may be possible to use the same technique to override whole type names as well.
But it seems like an awful lot of trouble to me. Instead, why not just handle the serialization explicitly:
private static string SerializeByLinqAndToString<T>(
List<T> data, string rootName, string elementName)
{
XDocument document = new XDocument(
new XElement(rootName, data.Select(s => new XElement(elementName, s))));
return SaveXmlToString(document);
}
private static string SaveXmlToString(XDocument document)
{
StringBuilder sb = new StringBuilder();
using (XmlWriter xmlWriter = XmlWriter.Create(sb,
new XmlWriterSettings { Indent = true, OmitXmlDeclaration = true }))
{
document.Save(xmlWriter);
}
return sb.ToString();
}
Call like this:
SomeConfiguration config = ...; // initialize as desired
string result = SerializeByLinq(config.Bugs, "bug", "bugs");
The above works only with a list of strings, or a list of types where the element content can be simply the result of calling ToString()
on the instance of the type.
Using the full-blown serialization features in .NET might be worthwhile when dealing with complex types, but if all you've got is a simple list of strings, the LINQ-to-XML feature is very handy.
If you do have more complex types, you can transform each list element into an XElement
for the DOM and serialize that:
private static string SerializeByLinq<T>(
List<T> data, string rootName, string elementName = null)
{
XDocument document = new XDocument(
new XElement(rootName, data.Select(t =>
ElementFromText(SerializeObject(t), elementName)
)));
return SaveXmlToString(document);
}
private static XElement ElementFromText(string xml, string name = null)
{
StringReader reader = new StringReader(xml);
XElement result = XElement.Load(reader);
if (!string.IsNullOrEmpty(name))
{
result.Name = name;
}
return result;
}
private static string SerializeObject<T>(T o)
{
XmlSerializer xmlSerializer = new XmlSerializer(typeof(T));
StringWriter textWriter = new StringWriter();
using (XmlWriter writer = XmlWriter.Create(textWriter,
new XmlWriterSettings { Indent = true, OmitXmlDeclaration = true }))
{
xmlSerializer.Serialize(writer, o,
new XmlSerializerNamespaces(new[] { XmlQualifiedName.Empty}));
}
return textWriter.ToString();
}
In this second example, you can omit the element name for the child, and it will just use whatever the type's set up to use already (e.g. the type name, or whatever [XmlRoot]
is set to).
How to add attributes for C# XML Serialization
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;
}
Related Topics
How to Backup and Restore the System Clipboard in C#
How to Treat the Circle as a Control After Drawing It? - Moving and Selecting Shapes
Mysqlcommand Command.Parameters.Add Is Obsolete
How to Select Text from the Richtextbox and Then Color It
Internet Explorer Protective Mode Setting and Zoom Levels
What Is the Worst Gotcha in C# or .Net
Are There Any Suggestions for Developing a C# Coding Standards/Best Practices Document
Super-Simple Example of C# Observer/Observable with Delegates
What Is the Best Scripting Language to Embed in a C# Desktop Application
Accessing Google Spreadsheets with C# Using Google Data API
How to Have an Enum Bound Combobox with Custom String Formatting for Enum Values
Differencebetween Int, Int16, Int32 and Int64
Verifying That a String Contains Only Letters in C#
How to Handle JSON That Returns Both a String and a String Array
Using the "Params" Keyword for Generic Parameters in C#
How to Read Data from a Zip File Without Having to Unzip the Entire File