Setting a XML Element Name and XML Attribute to a Class Property - c#

I have this Class that I want to convert to an XML Element
public class Person
{
[XmlElement(ElementName = "PersonName")]
public string Name { get; set; }
}
This will display an XML
<Person>
<PersonName>Smith</PersonName>
</Person>
I want to add an attribute to the element PersonName
<Person>
<PersonName required="true">Smith</PersonName>
</Person>
How would I do that?

I think you need a special class to hold your Name property, rather than relying on string. Here is an example, using the XmlText and XmlAttribute attributes to control how the built-in XmlSerializer works:
using System.Xml.Serialization;
using System.IO;
namespace SomeNamespace
{
class Program
{
static void Main(string[] args)
{
Person me = new Person("me");
string path = "C:\\temp\\person.xml";
XmlSerializer serializer = new XmlSerializer(typeof(Person));
using (StreamWriter sw = new StreamWriter(path))
{
serializer.Serialize(sw, me);
}
}
}
public class Person
{
public Person() { } // needed for serialization
public Person(string name)
{
Name = new PersonName(name);
}
[XmlElement(ElementName = "PersonName")]
public PersonName Name { get; set; }
}
public class PersonName
{
public PersonName() { } // needed for serialization
public PersonName(string name)
{
Name = name;
}
[XmlText]
public string Name { get; set; }
[XmlAttribute] // serializes as an Attribute
public bool Required { get; set; } = true;
}
}
output (at C:\temp\person.xml; you can change Main to serialize to string and print to console if you want):
<?xml version="1.0" encoding="utf-8"?>
<Person xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<PersonName Required="true">me</PersonName>
</Person>
If you really want your Required attribute to be serialized as the lowercase "required", you can use different properties of XmlAttribute, such as: XmlAttribute(AttributeName = "required")

Related

How to deserialize a given xml document [duplicate]

How do I Deserialize this XML document:
<?xml version="1.0" encoding="utf-8"?>
<Cars>
<Car>
<StockNumber>1020</StockNumber>
<Make>Nissan</Make>
<Model>Sentra</Model>
</Car>
<Car>
<StockNumber>1010</StockNumber>
<Make>Toyota</Make>
<Model>Corolla</Model>
</Car>
<Car>
<StockNumber>1111</StockNumber>
<Make>Honda</Make>
<Model>Accord</Model>
</Car>
</Cars>
I have this:
[Serializable()]
public class Car
{
[System.Xml.Serialization.XmlElementAttribute("StockNumber")]
public string StockNumber{ get; set; }
[System.Xml.Serialization.XmlElementAttribute("Make")]
public string Make{ get; set; }
[System.Xml.Serialization.XmlElementAttribute("Model")]
public string Model{ get; set; }
}
.
[System.Xml.Serialization.XmlRootAttribute("Cars", Namespace = "", IsNullable = false)]
public class Cars
{
[XmlArrayItem(typeof(Car))]
public Car[] Car { get; set; }
}
.
public class CarSerializer
{
public Cars Deserialize()
{
Cars[] cars = null;
string path = HttpContext.Current.ApplicationInstance.Server.MapPath("~/App_Data/") + "cars.xml";
XmlSerializer serializer = new XmlSerializer(typeof(Cars[]));
StreamReader reader = new StreamReader(path);
reader.ReadToEnd();
cars = (Cars[])serializer.Deserialize(reader);
reader.Close();
return cars;
}
}
that don't seem to work :-(
How about you just save the xml to a file, and use xsd to generate C# classes?
Write the file to disk (I named it foo.xml)
Generate the xsd: xsd foo.xml
Generate the C#: xsd foo.xsd /classes
Et voila - and C# code file that should be able to read the data via XmlSerializer:
XmlSerializer ser = new XmlSerializer(typeof(Cars));
Cars cars;
using (XmlReader reader = XmlReader.Create(path))
{
cars = (Cars) ser.Deserialize(reader);
}
(include the generated foo.cs in the project)
Here's a working version. I changed the XmlElementAttribute labels to XmlElement because in the xml the StockNumber, Make and Model values are elements, not attributes. Also I removed the reader.ReadToEnd(); (that function reads the whole stream and returns a string, so the Deserialize() function couldn't use the reader anymore...the position was at the end of the stream). I also took a few liberties with the naming :).
Here are the classes:
[Serializable()]
public class Car
{
[System.Xml.Serialization.XmlElement("StockNumber")]
public string StockNumber { get; set; }
[System.Xml.Serialization.XmlElement("Make")]
public string Make { get; set; }
[System.Xml.Serialization.XmlElement("Model")]
public string Model { get; set; }
}
[Serializable()]
[System.Xml.Serialization.XmlRoot("CarCollection")]
public class CarCollection
{
[XmlArray("Cars")]
[XmlArrayItem("Car", typeof(Car))]
public Car[] Car { get; set; }
}
The Deserialize function:
CarCollection cars = null;
string path = "cars.xml";
XmlSerializer serializer = new XmlSerializer(typeof(CarCollection));
StreamReader reader = new StreamReader(path);
cars = (CarCollection)serializer.Deserialize(reader);
reader.Close();
And the slightly tweaked xml (I needed to add a new element to wrap <Cars>...Net is picky about deserializing arrays):
<?xml version="1.0" encoding="utf-8"?>
<CarCollection>
<Cars>
<Car>
<StockNumber>1020</StockNumber>
<Make>Nissan</Make>
<Model>Sentra</Model>
</Car>
<Car>
<StockNumber>1010</StockNumber>
<Make>Toyota</Make>
<Model>Corolla</Model>
</Car>
<Car>
<StockNumber>1111</StockNumber>
<Make>Honda</Make>
<Model>Accord</Model>
</Car>
</Cars>
</CarCollection>
You have two possibilities.
Method 1. XSD tool
Suppose that you have your XML file in this location C:\path\to\xml\file.xml
Open Developer Command Prompt
You can find it in Start Menu > Programs > Microsoft Visual Studio 2012 > Visual Studio Tools
Or if you have Windows 8 can just start typing Developer Command Prompt in Start screen
Change location to your XML file directory by typing cd /D "C:\path\to\xml"
Create XSD file from your xml file by typing xsd file.xml
Create C# classes by typing xsd /c file.xsd
And that's it! You have generated C# classes from xml file in C:\path\to\xml\file.cs
Method 2 - Paste special
Required Visual Studio 2012+
Copy content of your XML file to clipboard
Add to your solution new, empty class file (Shift+Alt+C)
Open that file and in menu click Edit > Paste special > Paste XML As Classes
And that's it!
Usage
Usage is very simple with this helper class:
using System;
using System.IO;
using System.Web.Script.Serialization; // Add reference: System.Web.Extensions
using System.Xml;
using System.Xml.Serialization;
namespace Helpers
{
internal static class ParseHelpers
{
private static JavaScriptSerializer json;
private static JavaScriptSerializer JSON { get { return json ?? (json = new JavaScriptSerializer()); } }
public static Stream ToStream(this string #this)
{
var stream = new MemoryStream();
var writer = new StreamWriter(stream);
writer.Write(#this);
writer.Flush();
stream.Position = 0;
return stream;
}
public static T ParseXML<T>(this string #this) where T : class
{
var reader = XmlReader.Create(#this.Trim().ToStream(), new XmlReaderSettings() { ConformanceLevel = ConformanceLevel.Document });
return new XmlSerializer(typeof(T)).Deserialize(reader) as T;
}
public static T ParseJSON<T>(this string #this) where T : class
{
return JSON.Deserialize<T>(#this.Trim());
}
}
}
All you have to do now, is:
public class JSONRoot
{
public catalog catalog { get; set; }
}
// ...
string xml = File.ReadAllText(#"D:\file.xml");
var catalog1 = xml.ParseXML<catalog>();
string json = File.ReadAllText(#"D:\file.json");
var catalog2 = json.ParseJSON<JSONRoot>();
The following snippet should do the trick (and you can ignore most of the serialization attributes):
public class Car
{
public string StockNumber { get; set; }
public string Make { get; set; }
public string Model { get; set; }
}
[XmlRootAttribute("Cars")]
public class CarCollection
{
[XmlElement("Car")]
public Car[] Cars { get; set; }
}
...
using (TextReader reader = new StreamReader(path))
{
XmlSerializer serializer = new XmlSerializer(typeof(CarCollection));
return (CarCollection) serializer.Deserialize(reader);
}
See if this helps:
[Serializable()]
[System.Xml.Serialization.XmlRootAttribute("Cars", Namespace = "", IsNullable = false)]
public class Cars
{
[XmlArrayItem(typeof(Car))]
public Car[] Car { get; set; }
}
.
[Serializable()]
public class Car
{
[System.Xml.Serialization.XmlElement()]
public string StockNumber{ get; set; }
[System.Xml.Serialization.XmlElement()]
public string Make{ get; set; }
[System.Xml.Serialization.XmlElement()]
public string Model{ get; set; }
}
And failing that use the xsd.exe program that comes with visual studio to create a schema document based on that xml file, and then use it again to create a class based on the schema document.
I don't think .net is 'picky about deserializing arrays'. The first xml document is not well formed.
There is no root element, although it looks like there is. The canonical xml document has a root and at least 1 element (if at all). In your example:
<Root> <-- well, the root
<Cars> <-- an element (not a root), it being an array
<Car> <-- an element, it being an array item
...
</Car>
</Cars>
</Root>
try this block of code if your .xml file has been generated somewhere in disk and if you have used List<T>:
//deserialization
XmlSerializer xmlser = new XmlSerializer(typeof(List<Item>));
StreamReader srdr = new StreamReader(#"C:\serialize.xml");
List<Item> p = (List<Item>)xmlser.Deserialize(srdr);
srdr.Close();`
Note: C:\serialize.xml is my .xml file's path. You can change it for your needs.
For Beginners
I found the answers here to be very helpful, that said I still struggled (just a bit) to get this working. So, in case it helps someone I'll spell out the working solution:
XML from Original Question. The xml is in a file Class1.xml, a path to this file is used in the code to locate this xml file.
I used the answer by #erymski to get this working, so created a file called Car.cs and added the following:
using System.Xml.Serialization; // Added
public class Car
{
public string StockNumber { get; set; }
public string Make { get; set; }
public string Model { get; set; }
}
[XmlRootAttribute("Cars")]
public class CarCollection
{
[XmlElement("Car")]
public Car[] Cars { get; set; }
}
The other bit of code provided by #erymski ...
using (TextReader reader = new StreamReader(path))
{
XmlSerializer serializer = new XmlSerializer(typeof(CarCollection));
return (CarCollection) serializer.Deserialize(reader);
}
... goes into your main program (Program.cs), in static CarCollection XCar() like this:
using System;
using System.IO;
using System.Xml.Serialization;
namespace ConsoleApp2
{
class Program
{
public static void Main()
{
var c = new CarCollection();
c = XCar();
foreach (var k in c.Cars)
{
Console.WriteLine(k.Make + " " + k.Model + " " + k.StockNumber);
}
c = null;
Console.ReadLine();
}
static CarCollection XCar()
{
using (TextReader reader = new StreamReader(#"C:\Users\SlowLearner\source\repos\ConsoleApp2\ConsoleApp2\Class1.xml"))
{
XmlSerializer serializer = new XmlSerializer(typeof(CarCollection));
return (CarCollection)serializer.Deserialize(reader);
}
}
}
}
Hope it helps :-)
Kevin's anser is good, aside from the fact, that in the real world, you are often not able to alter the original XML to suit your needs.
There's a simple solution for the original XML, too:
[XmlRoot("Cars")]
public class XmlData
{
[XmlElement("Car")]
public List<Car> Cars{ get; set; }
}
public class Car
{
public string StockNumber { get; set; }
public string Make { get; set; }
public string Model { get; set; }
}
And then you can simply call:
var ser = new XmlSerializer(typeof(XmlData));
var data = (XmlData)ser.Deserialize(XmlReader.Create(PathToCarsXml));
One liner:
var object = (Cars)new XmlSerializer(typeof(Cars)).Deserialize(new StringReader(xmlString));
Try this Generic Class For Xml Serialization & Deserialization.
public class SerializeConfig<T> where T : class
{
public static void Serialize(string path, T type)
{
var serializer = new XmlSerializer(type.GetType());
using (var writer = new FileStream(path, FileMode.Create))
{
serializer.Serialize(writer, type);
}
}
public static T DeSerialize(string path)
{
T type;
var serializer = new XmlSerializer(typeof(T));
using (var reader = XmlReader.Create(path))
{
type = serializer.Deserialize(reader) as T;
}
return type;
}
}
How about a generic class to deserialize an XML document
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Generic class to load any xml into a class
// used like this ...
// YourClassTypeHere InfoList = LoadXMLFileIntoClass<YourClassTypeHere>(xmlFile);
using System.IO;
using System.Xml.Serialization;
public static T LoadXMLFileIntoClass<T>(string xmlFile)
{
T returnThis;
XmlSerializer serializer = new XmlSerializer(typeof(T));
if (!FileAndIO.FileExists(xmlFile))
{
Console.WriteLine("FileDoesNotExistError {0}", xmlFile);
}
returnThis = (T)serializer.Deserialize(new StreamReader(xmlFile));
return (T)returnThis;
}
This part may, or may not be necessary. Open the XML document in Visual Studio, right click on the XML, choose properties. Then choose your schema file.
The idea is to have all level being handled for deserialization
Please see a sample solution that solved my similar issue
<?xml version="1.0" ?>
<TRANSACTION_RESPONSE>
<TRANSACTION>
<TRANSACTION_ID>25429</TRANSACTION_ID>
<MERCHANT_ACC_NO>02700701354375000964</MERCHANT_ACC_NO>
<TXN_STATUS>F</TXN_STATUS>
<TXN_SIGNATURE>a16af68d4c3e2280e44bd7c2c23f2af6cb1f0e5a28c266ea741608e72b1a5e4224da5b975909cc43c53b6c0f7f1bbf0820269caa3e350dd1812484edc499b279</TXN_SIGNATURE>
<TXN_SIGNATURE2>B1684258EA112C8B5BA51F73CDA9864D1BB98E04F5A78B67A3E539BEF96CCF4D16CFF6B9E04818B50E855E0783BB075309D112CA596BDC49F9738C4BF3AA1FB4</TXN_SIGNATURE2>
<TRAN_DATE>29-09-2015 07:36:59</TRAN_DATE>
<MERCHANT_TRANID>150929093703RUDZMX4</MERCHANT_TRANID>
<RESPONSE_CODE>9967</RESPONSE_CODE>
<RESPONSE_DESC>Bank rejected transaction!</RESPONSE_DESC>
<CUSTOMER_ID>RUDZMX</CUSTOMER_ID>
<AUTH_ID />
<AUTH_DATE />
<CAPTURE_DATE />
<SALES_DATE />
<VOID_REV_DATE />
<REFUND_DATE />
<REFUND_AMOUNT>0.00</REFUND_AMOUNT>
</TRANSACTION>
</TRANSACTION_RESPONSE>
The above XML is handled in two level
[XmlType("TRANSACTION_RESPONSE")]
public class TransactionResponse
{
[XmlElement("TRANSACTION")]
public BankQueryResponse Response { get; set; }
}
The Inner level
public class BankQueryResponse
{
[XmlElement("TRANSACTION_ID")]
public string TransactionId { get; set; }
[XmlElement("MERCHANT_ACC_NO")]
public string MerchantAccNo { get; set; }
[XmlElement("TXN_SIGNATURE")]
public string TxnSignature { get; set; }
[XmlElement("TRAN_DATE")]
public DateTime TranDate { get; set; }
[XmlElement("TXN_STATUS")]
public string TxnStatus { get; set; }
[XmlElement("REFUND_DATE")]
public DateTime RefundDate { get; set; }
[XmlElement("RESPONSE_CODE")]
public string ResponseCode { get; set; }
[XmlElement("RESPONSE_DESC")]
public string ResponseDesc { get; set; }
[XmlAttribute("MERCHANT_TRANID")]
public string MerchantTranId { get; set; }
}
Same Way you need multiple level with car as array
Check this example for multilevel deserialization
If you're getting errors using xsd.exe to create your xsd file, then use the XmlSchemaInference class as mentioned on msdn. Here's a unit test to demonstrate:
using System.Xml;
using System.Xml.Schema;
[TestMethod]
public void GenerateXsdFromXmlTest()
{
string folder = #"C:\mydir\mydata\xmlToCSharp";
XmlReader reader = XmlReader.Create(folder + "\some_xml.xml");
XmlSchemaSet schemaSet = new XmlSchemaSet();
XmlSchemaInference schema = new XmlSchemaInference();
schemaSet = schema.InferSchema(reader);
foreach (XmlSchema s in schemaSet.Schemas())
{
XmlWriter xsdFile = new XmlTextWriter(folder + "\some_xsd.xsd", System.Text.Encoding.UTF8);
s.Write(xsdFile);
xsdFile.Close();
}
}
// now from the visual studio command line type: xsd some_xsd.xsd /classes
You can just change one attribute for you Cars car property from XmlArrayItem to XmlElment. That is, from
[System.Xml.Serialization.XmlRootAttribute("Cars", Namespace = "", IsNullable = false)]
public class Cars
{
[XmlArrayItem(typeof(Car))]
public Car[] Car { get; set; }
}
to
[System.Xml.Serialization.XmlRootAttribute("Cars", Namespace = "", IsNullable = false)]
public class Cars
{
[XmlElement("Car")]
public Car[] Car { get; set; }
}
My solution:
Use Edit > Past Special > Paste XML As Classes to get the class in your code
Try something like this: create a list of that class (List<class1>), then use the XmlSerializer to serialize that list to a xml file.
Now you just replace the body of that file with your data and try to deserialize it.
Code:
StreamReader sr = new StreamReader(#"C:\Users\duongngh\Desktop\Newfolder\abc.txt");
XmlSerializer xml = new XmlSerializer(typeof(Class1[]));
var a = xml.Deserialize(sr);
sr.Close();
NOTE: you must pay attention to the root name, don't change it. Mine is "ArrayOfClass1"

Writing Xml Class in c#

I have a xml file like this:
<?xml version="1.0" encoding="UTF-8"?>
<Configuration xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Devices>
<Settings>
<Name>ABC</DeviceName>
<HostNic>LAN_1</HostNic>
</Settings>
</Devices>
</Configuration>
I want to deserialize this to object form. I am trying to define a class structure for the xml file like this:
class Configuration
{
[XmlElement("Address")]
public List<Devices> deviceList = new List<Devices>();
}
class Devices
{
[XmlElement("Address")]
public List<Settings> settingList = new List<Settings>();
}
class Settings
{
public string Name { get; set; }
public string HostNic { get; set; }
}
Is there any other appropriate way of defining class for this xml file?
Your Classes need some modifications, specially the attributes you have added.
[XmlRoot]
public class Configuration
{
[XmlElement("Devices")]
public List<Devices> deviceList = new List<Devices>();
}
public class Devices
{
[XmlElement("Settings")]
public List<Settings> settingList = new List<Settings>();
}
public class Settings
{
public string Name { get; set; }
public string HostNic { get; set; }
}
Then you can de-serialize the XML into the above classes:
var serializer = new XmlSerializer(typeof(Configuration));
using (System.IO.TextReader reader = new System.IO.StringReader(<Your XML String>))
{
Configuration config = (Configuration)serializer.Deserialize(reader);
}

Adding Qualified NameSpace in XML using C#

How can I create XML given below in c#
<v1:Request ProductId="string" xmlns:v1="com/user/service/core/services/v1" xmlns:v11="com/user/ds/sch/pii/v1" xmlns:enum="com/uaer/schema/database/tcps/enumerations">
<v1:Name>string</v1:Name>
<v1:ID>string</v1:ID>
<v1:Code>string</v1:Code>
<v1:Key>string</v1:Key>
<v1:RequestKey>string</v1:RequestKey>
<v1:PartnerId>string</v1:PartnerId>
<v1:CustomerInfo>
<v1:Name>
<v11:Title>string</v11:Title>
<v11:Forename>string</v11:Forename>
<v11:Surname>string</v11:Surname>
<v11:Suffix>string</v11:Suffix>
</v1:Name>
<v1:Number>
<v11:Name>string</v11:Name>
<v11:Id>string</v11:Id>
</v1:Number>
</v1:Request>
Code snippet that i am using to generate the XML is this,
[XmlRoot("Request")]
public class Request{
[XmlAttribute]
public string ProductId{get;set;}
[XmlElement("Name")]
public string Name{get;set;}
[XmlElement("ID")]
public string ID{get;set;}
[XmlElement("Code")]
public string Code{get;set;}
[XmlElement("Key")]
public string Key{get;set;}
[XmlElement("RequestKey")]
public string RequestKey{get;set;}
[XmlElement("PartnerId")]
public string PartnerId{get;set;}
[XmlElement("CustomerInfo")]
public CustomerInfo CustomerInfo= new CustomerInfo();
//this(CustomerInfo) is a class which contains the reference of NAME and NUMBER class.
//NAME and NUMBER class contains their respective properties.
}
I am able to generate this XML using the above code
<Request ProductId="string" xmlns:v1="com/user/service/core/services/v1" xmlns:v11="com/user/ds/sch/pii/v1" xmlns:enum="com/uaer/schema/database/tcps/enumerations">
<Name>string</Name>
<ID>string</ID>
<Code>string</Code>
<Key>string</Key>
<RequestKey>string</RequestKey>
<PartnerId>string</PartnerId>
<CustomerInfo>
<Name>
<Title>string</Title>
<Forename>string</Forename>
<Surname>string</Surname>
<Suffix>string</Suffix>
</Name>
<Number>
<Name>string</Name>
<Id>string</Id>
</Number>
</Request>
I am adding namespace using XmlSerializerNamespaces
I am trying to consume SOAP Api and i have to pass the xml as request.
You can combine multiple namespaces by adding them to XML attributes:
[XmlRoot("Request", Namespace = "com/user/service/core/services/v1")]
public class Request
{
[XmlAttribute]
public string ProductId { get; set; }
[XmlElement("Name")]
public string Name { get; set; }
[XmlElement("CustomerInfo")]
public CustomerInfo CustomerInfo = new CustomerInfo();
}
public class CustomerInfo
{
[XmlElement("Name")]
public Name Name { get; set; }
}
public class Name
{
[XmlElement("Title", Namespace = "com/user/ds/sch/pii/v1")]
public string Title { get; set; }
}
The namespace prefixes are provided to the XML serializer:
XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
ns.Add("v1", "com/user/service/core/services/v1");
ns.Add("v11", "com/user/ds/sch/pii/v1");
XmlSerializer xser = new XmlSerializer(typeof(Request));
xser.Serialize(Console.Out, new Request(), ns);

Remove p2:type="<<type>>" xmlns:p2="http://www.w3.org/2001/XMLSchema-instance" from xml

How to remove xmlns from all the inner nodes of the xml. I was able to remove the xmlns from the root node but still the inner node has all the xmlns in the inner node.
public class Program
{
public static void Main()
{
List<Person> students = new List<Person>();
Student std1 = new Student() { Name="Name1", StudentId = 1};
students.Add(std1);
Student std2 = new Student() { Name = "Name2", StudentId = 2 };
students.Add(std2);
string data = students.ToList().ToXML();
}
}
[System.Xml.Serialization.XmlInclude(typeof(Student))]
public class Person
{
public string Name { get; set; }
}
public class Student : Person
{
public int StudentId { get; set; }
}
ToXML()
public static string ToXML<T>(this T value)
{
if (value.IsNull()) return string.Empty;
var xmlSerializer = new XmlSerializer(typeof(T));
XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
ns.Add("", "");
using (var stringWriter = new StringWriter())
{
using (var xmlWriter = XmlWriter.Create(stringWriter, new XmlWriterSettings { OmitXmlDeclaration = true, Indent = false }))
{
xmlSerializer.Serialize(xmlWriter, value, ns);
return stringWriter.ToString();
}
}
}
Output is
<ArrayOfPerson>
<Person p2:type="Student" xmlns:p2="http://www.w3.org/2001/XMLSchema-instance">
<Name>Name1</Name>
<StudentId>1</StudentId>
</Person>
<Person p2:type="Student" xmlns:p2="http://www.w3.org/2001/XMLSchema-instance">
<Name>Name2</Name>
<StudentId>2</StudentId>
</Person>
</ArrayOfPerson>
Expected output is
<ArrayOfPerson>
<Person>
<Name>Name1</Name>
<StudentId>1</StudentId>
</Person>
<Person>
<Name>Name2</Name>
<StudentId>2</StudentId>
</Person>
</ArrayOfPerson>
After you do the XML serialization in your code you can apply the RemoveAllNamespaces() function from this answer:
How to remove all namespaces from XML with C#?
This is being added because you're serialising a list of Person but are using a sub-type of Student. The type attributes are required for the serialiser to determine the actual type being used.
If you don't want these attributes and you only have a single type of 'person', then you should collapse the definitions of Student and Person:
public class Person
{
public string Name { get; set; }
public int StudentId { get; set; }
}
[XmlElement("Person", Type = typeof(Student))]
List<Person> students = new List<Person>();
then remove your include
Took me forever to figure this one out
In my case the output was like this:
<ArrayOfPerson>
<Person>
<Name xmlns:p2="http://www.w3.org/2001/XMLSchema-instance"/>
<StudentId>1</StudentId>
</Person>
</ArrayOfPerson>
The xmlns polluted the child property, this is happening when the property is empty (null) and the property name in the class is fixtured with
IsNullable = true
Like:
[XmlElement(IsNullable = true)]
public string Name { get; set; }
So just change it false in case you want to remove the xmlns:p2 from the child property:
[XmlElement(IsNullable = false)]
public string Name { get; set; }

Controlling XML Serialization of a List<> derived class

I'm converting a Dictionary object into a List<> derived class by means of the following two declarations:
[Serializable]
public class LogItem
{
public string Name { get; set; }
public string Value { get; set; }
public LogItem(string key, string value)
{
Name = key; Value = value;
}
public LogItem() { }
}
public class SerializableDictionary : List<LogItem>
{
public SerializableDictionary(Dictionary<string, string> table)
{
IDictionaryEnumerator index = table.GetEnumerator();
while (index.MoveNext())
{
Put(index.Key.ToString(), index.Value.ToString());
}
}
private void Put(string key, string value)
{
base.Add(new LogItem(key, value));
}
}
I intend to serialize SerializableDictionary by means of the following code:
SerializableDictionary log = new SerializableDictionary(contents);
using (StringWriter xmlText = new StringWriter())
{
XmlSerializer xmlFormat =
new XmlSerializer(typeof(SerializableDictionary), new XmlRootAttribute("Log"));
xmlFormat.Serialize(xmlText, log);
}
Works fine, but I'm unable to change the XML formatting.
This XML document is intended to be sent to a xml database field and is not meant to be deserialized.
I'd rather have both Name and Value
formatted as attributes of the
LogItem element.
However any attempts at using XMLAttribute have resulted in Reflection or compilation errors. I'm at loss as to what I can do to achieve this requirement. Could someone please help?
you can annotate them with XmlAttribute:
[Serializable]
public class LogItem
{
[XmlAttribute]
public string Name { get; set; }
[XmlAttribute]
public string Value { get; set; }
public LogItem(string key, string value)
{
Name = key; Value = value;
}
public LogItem() { }
}
This worked fine for me and produced the following XML (based on sample input):
<?xml version="1.0" encoding="utf-16"?>
<Log xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<LogItem Name="foo" Value="bar" />
<LogItem Name="asdf" Value="bcxcvxc" />
</Log>
There must be something else going on besides what you are showing. I am able to compile and execute the above code both with and without the XmlAttribute attribute applied to the Name and Value properties.
[XmlAttribute]
public string Name { get; set; }
[XmlAttribute]
public string Value { get; set; }

Categories