I am trying to read a xml file and deserialize it to my InsertSensorType class and than read VALUE1,VALUE2 .. .I tried to add XmlElement name to my InsertionMetadata attribute in InsertSensorTypeMetadata class, but it doesn't work.I have searched and found solutions but they were not valid for this problem. Can anyone please tell me what i am doing wrong.
Xml File :
<?xml version="1.0" encoding="utf-8" ?>
<swes:InsertSensor
xmlns:swes="http://www.opengis.net/swes/2.0"
xmlns:sos="http://www.opengis.net/sos/2.0" >
<swes:metadata>
<sos:SosInsertionMetadata>
<sos:observationType>VALUE1</sos:observationType>
<sos:observationType>VALUE2</sos:observationType>
<sos:featureOfInterestType>VALUE3</sos:featureOfInterestType>
<sos:featureOfInterestType>VALUE4</sos:featureOfInterestType>
</sos:SosInsertionMetadata>
</swes:metadata>
</swes:InsertSensor>
My Classes :
namespace Problem1.Classes
{
[SerializableAttribute()]
[XmlTypeAttribute(Namespace = "http://www.opengis.net/swes/2.0")]
[XmlRootAttribute("InsertSensor", Namespace = "http://www.opengis.net/swes/2.0", IsNullable = false)]
public class InsertSensorType
{
[System.Xml.Serialization.XmlElementAttribute("metadata")]
public InsertSensorTypeMetadata[] metadata { get; set; }
}
[SerializableAttribute()]
[XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.opengis.net/swes/2.0")]
public class InsertSensorTypeMetadata
{
[XmlElement(ElementName = "SosInsertionMetadata", Type = typeof(SosInsertionMetadataType))]
public InsertionMetadataType InsertionMetadata { get; set; }
}
[XmlIncludeAttribute(typeof(SosInsertionMetadataType))]
[SerializableAttribute()]
[XmlTypeAttribute(Namespace = "http://www.opengis.net/swes/2.0")]
public abstract partial class InsertionMetadataType
{
}
[SerializableAttribute()]
[XmlTypeAttribute(Namespace = "http://www.opengis.net/sos/2.0")]
public partial class SosInsertionMetadataType : InsertionMetadataType
{
[System.Xml.Serialization.XmlElementAttribute("observationType", DataType = "anyURI")]
public string[] observationType { get; set; }
[System.Xml.Serialization.XmlElementAttribute("featureOfInterestType", DataType = "anyURI")]
public string[] featureOfInterestType { get; set; }
}
}
And here is my main code :
static void Main(string[] args)
{
XmlElement xmlRequest = null;
XmlDocument doc = new XmlDocument();
doc.Load("request.xml");
xmlRequest = doc.DocumentElement;
executeRequest(xmlRequest);
}
static void executeRequest(XmlElement xmlRequest)
{
InsertSensorType insertSensorRequest = ValidateRequest<InsertSensorType>(xmlRequest);
InsertSensorTypeMetadata[] _InsertSensorTypeMetadata = insertSensorRequest.metadata;
Console.WriteLine("Length of metadata :" + _InsertSensorTypeMetadata.Length);//1
foreach (InsertSensorTypeMetadata istm in _InsertSensorTypeMetadata)
{
SosInsertionMetadataType sos = istm.InsertionMetadata as SosInsertionMetadataType;
//sos is null
}
Console.Read();
}
static T ValidateRequest<T>(XmlElement xmlRequest) where T : class
{
string xml = xmlRequest.OuterXml;
StringReader reader = new StringReader(xml);
XmlSerializer serializer = new XmlSerializer(typeof(T));
//XmlSerializer serializer = new XmlSerializer(typeof(T), new Type[] { typeof(SosInsertionMetadataType) });
T typeInstance = (T)serializer.Deserialize(reader);
return typeInstance;
}
Try this
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Serialization;
using System.IO;
namespace ConsoleApplication1
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
InsertSensorType insertSensorType = new InsertSensorType() {
metadata = new Metadata() {
insertSensorTypeMetadata = new InsertSensorTypeMetadata() {
InsertionMetadata = new List<InsertionMetadataType>() {
new ObservationType() { value = "Value1"},
new ObservationType() { value = "Value2"},
new FeatureOfInterestType() { value = "Value3"},
new FeatureOfInterestType() { value = "Value4"}
}
}
}
};
XmlSerializer serializer = new XmlSerializer(typeof(InsertSensorType));
XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
ns.Add("swes","http://www.opengis.net/swes/2.0");
ns.Add("sos","http://www.opengis.net/sos/2.0");
StreamWriter writer = new StreamWriter(FILENAME);
serializer.Serialize(writer, insertSensorType, ns);
writer.Flush();
writer.Close();
writer.Dispose();
XmlSerializer xs = new XmlSerializer(typeof(InsertSensorType));
XmlTextReader reader = new XmlTextReader(FILENAME);
InsertSensorType newInsertSensorType = (InsertSensorType)xs.Deserialize(reader);
}
}
[XmlRoot(ElementName = "InsertSensor")]
public class InsertSensorType
{
[XmlElement("metadata")]
public Metadata metadata { get; set; }
}
[XmlRoot("metadata", Namespace = "http://www.opengis.net/swes/2.0")]
public class Metadata
{
[XmlElement("SosInsertionMetadata")]
public InsertSensorTypeMetadata insertSensorTypeMetadata { get; set; }
}
[XmlRoot("SosInsertionMetadata", Namespace = "http://www.opengis.net/sos/2.0")]
public class InsertSensorTypeMetadata
{
[XmlElement()]
public List<InsertionMetadataType> InsertionMetadata { get; set; }
}
[XmlInclude(typeof(ObservationType))]
[XmlInclude(typeof(FeatureOfInterestType))]
[Serializable]
[XmlRoot(Namespace = "http://www.opengis.net/sos/2.0")]
public class InsertionMetadataType
{
public string value { get; set; }
}
[Serializable]
[XmlRoot(ElementName = "observationType", Namespace = "http://www.opengis.net/sos/2.0")]
public class ObservationType : InsertionMetadataType
{
}
[Serializable]
[XmlRoot(ElementName = "featureOfInterestType", Namespace = "http://www.opengis.net/sos/2.0")]
public class FeatureOfInterestType : InsertionMetadataType
{
}
}
My solution is that :
added this line to over InsertionMetadata attribute in InsertSensorTypeMetadata class
[System.Xml.Serialization.XmlElement(ElementName = "SosInsertionMetadata", Type = typeof(SosInsertionMetadataType), Namespace = "http://www.opengis.net/sos/2.0")] // added
change my deserialize method
public static T ValidateRequest<T>(XmlElement element) where T : class
{
var serializer = new XmlSerializer(typeof(T));
return (T)serializer.Deserialize(new XmlNodeReader(element));
}
and changed way to print values
static void executeRequest(XmlElement xmlRequest)
{
InsertSensorType insertSensorRequest = ValidateRequest<InsertSensorType>(xmlRequest);
foreach (InsertSensorTypeMetadata istm in insertSensorRequest.metadata)
{
SosInsertionMetadataType sos = (SosInsertionMetadataType)istm.InsertionMetadata;
foreach(string s in sos.featureOfInterestType)
Console.WriteLine(s);
foreach (string s in sos.observationType)
Console.WriteLine(s);
}
}
Related
Since XmlSerializer can not serialize any other properties when the class is inherited from List <>, I try to solve them with the DataContractSerializer. This should work, as described here: When a class is inherited from List<>, XmlSerializer doesn't serialize other attributes
But I get the same results. If the object is inherited from List <> the TestValue property is not serialized.
using System.Runtime.Serialization;
[Serializable]
public class XSerBase
{
[DataMember]
public XSerTest XSerTest { get; set; } = new XSerTest();
}
[Serializable]
public class XSerTest : List<string>
{
[DataMember]
public string TestValue { get; set; }
}
{// my serialize / deserialize example
XSerBase objectSource = new XSerBase();
objectSource.XSerTest.TestValue = "QWERT";
MemoryStream mem = new MemoryStream();
DataContractSerializer dcsSource = new DataContractSerializer(typeof(XSerBase));
dcsSource.WriteObject(mem, objectSource);
mem.Position = 0;
XSerBase objectDestination = null;
DataContractSerializer dcsDestination = new DataContractSerializer(typeof(XSerBase));
objectDestination = (dcsDestination.ReadObject(mem) as XSerBase);
// objectDestination.XSerTest.TestValue is null
// objectDestination.XSerTest.TestValue is "QWERT", when XSerTest is not inherited from List<string>
}
Am I missing an attribute?
I tried to get an inherited class List to work and was not successful. This is the best I could do
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Globalization;
using System.Xml;
using System.Xml.Serialization;
namespace ConsoleApplication106
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
XSerBase test = new XSerBase()
{
XSerTest = new List<XSerTest>() {
new XSerTest() { TestValue = "123"},
new XSerTest() { TestValue = "456"}
}
};
XmlSerializer serializer = new XmlSerializer(typeof(XSerBase));
XmlWriterSettings settings = new XmlWriterSettings();
settings.Indent = true;
XmlWriter writer = XmlWriter.Create(FILENAME,settings);
serializer.Serialize(writer, test);
writer.Flush();
writer.Close();
}
}
public class XSerBase
{
[XmlElement("XSerTest")]
public List<XSerTest> XSerTest { get; set; }
}
public class XSerTest
{
public string TestValue { get; set; }
}
}
I'm trying to obtain the value of the logicalName attribute of the main node of this xml file:
<?xml version="1.0" encoding="ISO-8859-1"?>
<ticketlayout xmlns="http://www.example.com/ticketlayout" logicalName="target.xml" deviceCode="1" measurement="mm" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.example.com/ticketlayout">
<fontdefinition id="BarCode">
<fontname>Code128bWin</fontname>
<size measure="pt">16</size>
</fontdefinition>
</ticketlayout>
I've tried to add the namespace "xsi", "http://www.w3.org/2001/XMLSchema-instance" this way:
XmlDocument fLayout = new XmlDocument();
fLayout.Load("myFile.xml");
XmlNamespaceManager nsmRequestLayout = new XmlNamespaceManager(fLayout.NameTable);
nsmRequestLayout.AddNamespace("xsi", "http://www.w3.org/2001/XMLSchema-instance");
string sValue = fLayout.SelectNodes("//ticketlayout", nsmRequestLayout)[0].Attributes["name"].Value;
But I get no nodes. I've tried without namespace and no nodes again, and son on.
¿Could please anyone help me?
Thanks in advance.
If you want to get the value : target.xml
Try this code
XmlDocument fLayout = new XmlDocument();
fLayout.Load("myFile.xml"); // your XML file
var attrib = fLayout["ticketlayout"].Attributes["logicalName"].Value;
First of all your XML is not valid.
I modified to look this way in order to achieve what you are looking for.
XML File :
<?xml version="1.0" encoding="UTF-8"?>
<ticketlayout xmlns="http://www.example.com/ticketlayout" logicalName="target.xml" deviceCode="1" measurement="mm" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.example.com/ticketlayout">
<fontdefinition id="BarCode">
<fontname>Code128bWin</fontname>
<size measure="pt">16</size>
</fontdefinition>
</ticketlayout>
I am not sure why you would not have a model structure to deserialize you xml, and then access whatever property/attribute you need.
Example :
Classes:
[XmlRoot(ElementName = "size", Namespace = "http://www.example.com/ticketlayout")]
public class Size
{
[XmlAttribute(AttributeName = "measure")]
public string Measure { get; set; }
[XmlText]
public string Text { get; set; }
}
[XmlRoot(ElementName = "fontdefinition", Namespace = "http://www.example.com/ticketlayout")]
public class Fontdefinition
{
[XmlElement(ElementName = "fontname", Namespace = "http://www.example.com/ticketlayout")]
public string Fontname { get; set; }
[XmlElement(ElementName = "size", Namespace = "http://www.example.com/ticketlayout")]
public Size Size { get; set; }
[XmlAttribute(AttributeName = "id")]
public string Id { get; set; }
}
[XmlRoot(ElementName = "ticketlayout", Namespace = "http://www.example.com/ticketlayout")]
public class Ticketlayout
{
[XmlElement(ElementName = "fontdefinition", Namespace = "http://www.example.com/ticketlayout")]
public Fontdefinition Fontdefinition { get; set; }
[XmlAttribute(AttributeName = "xmlns")]
public string Xmlns { get; set; }
[XmlAttribute(AttributeName = "logicalName")]
public string LogicalName { get; set; }
[XmlAttribute(AttributeName = "deviceCode")]
public string DeviceCode { get; set; }
[XmlAttribute(AttributeName = "measurement")]
public string Measurement { get; set; }
[XmlAttribute(AttributeName = "xsi", Namespace = "http://www.w3.org/2000/xmlns/")]
public string Xsi { get; set; }
[XmlAttribute(AttributeName = "schemaLocation", Namespace = "http://www.w3.org/2001/XMLSchema-instance")]
public string SchemaLocation { get; set; }
}
Then you could use a serializer :
public class Serializer
{
public T Deserialize<T>(string input) where T : class
{
XmlSerializer xmlSerializer = new XmlSerializer(typeof(T));
using (StringReader stringReader = new StringReader(input))
{
return (T)xmlSerializer.Deserialize(stringReader);
}
}
public string Serialize<T>(T ObjectToSerialize)
{
XmlSerializer xmlSerializer = new XmlSerializer(ObjectToSerialize.GetType());
StringBuilder builder = new StringBuilder();
using (StringWriterWithEncoding textWriter = new StringWriterWithEncoding(builder, Encoding.UTF8))
{
xmlSerializer.Serialize(textWriter, ObjectToSerialize);
return textWriter.ToString();
}
}
}
public class StringWriterWithEncoding : StringWriter
{
Encoding encoding;
public StringWriterWithEncoding(StringBuilder builder, Encoding encoding)
: base(builder)
{
this.encoding = encoding;
}
public override Encoding Encoding
{
get { return encoding; }
}
}
And finally you can access whatever you want by doing the following :
var serializer = new Serializer();
//I used a local file for testing, but it should be the same thing with your file
var xmlInputData = File.ReadAllText(#"MyXmlPath");
var output = serializer.Deserialize<Ticketlayout >(xmlInputData);
var logicalName = output.LogicalName;
I have a class need to be serialized.
namespace serializedobject
{
[DataContract]
public class Class1
{
string string1_;
string string2_;
EntityA entity_;
[DataMember]
public string string3
{
get { return string1_; }
set { string1_ = value; }
}
[DataMember]
public string string2
{
get { return string2_; }
set { string2_ = value; }
}
[DataMember]
public EntityA Entity
{
get { return entity_; }
set { entity_ = value; }
}
public static Class1 FromXML(string desc)
{
using (MemoryStream ms = new MemoryStream())
{
StreamWriter writer = new StreamWriter(ms);
writer.Write(desc);
writer.Flush();
ms.Seek(0, 0);
DataContractSerializer ser = new DataContractSerializer(typeof(Class1));
return (Class1)ser.ReadObject(ms);
}
}
public string ToXML()
{
using (MemoryStream ms = new MemoryStream())
{
DataContractSerializer ser = new DataContractSerializer(typeof(Class1));
ser.WriteObject(ms, this);
ms.Seek(0, 0);
StreamReader reader = new StreamReader(ms);
return reader.ReadToEnd();
}
}
}
[DataContract]
public class EntityA
{
string name_;
[DataMember]
public string Name
{
get { return name_; }
set { name_ = value; }
}
}
}
it is works fine with FromXML and ToXML. one of serialized context like:
<Class1 xmlns="http://schemas.datacontract.org/2004/07/serializedobject" xmlns:i="http://www.w3.org/2001/XMLSchema-instance"><Entity><Name>az</Name></Entity><string2 i:nil="true"/><string3>test</string3></Class1>
Later I need to move class EntityA to another namespace "outside", now the serialized context like:
<Class1 xmlns="http://schemas.datacontract.org/2004/07/serializedobject" xmlns:i="http://www.w3.org/2001/XMLSchema-instance"><Entity xmlns:a="http://schemas.datacontract.org/2004/07/outside"><a:Name>az</a:Name></Entity><string2 i:nil="true"/><string3>test</string3></Class1>
but now the serialized xml which created before change namespace can't be deserialized correctly. I guess this is because of for class "EntityA" changed namespace (xmlns:a added).
does anybody run into the problem before? any suggestion?
You can stop the namespace being added to the XML by specifying [DataContract(Namespace="")]. This relies on you setting that attribute BEFORE you save any xml code.
You can use this approach only if you have not already serialized any data, so this is the approach you would use when first designing a class to be serialized.
(If you have already got serialized data that you must deal with, see the second part of my answer below.)
This code sample has the two classes called Demo in two different namespaces, Test1 and Test2.
We serialize the code using the class from one namespace, and deserialize it using the class from the other namespace:
using System;
using System.IO;
using System.Runtime.Serialization;
using System.Xml;
namespace ConsoleApp1
{
namespace Test1
{
[DataContract(Namespace="")]
public sealed class Demo
{
[DataMember]
public string Value { get; set; }
}
}
namespace Test2
{
[DataContract(Namespace="")]
public sealed class Demo
{
[DataMember]
public string Value { get; set; }
}
}
sealed class Program
{
private void run()
{
string filename = Path.GetTempFileName();
var demo1 = new Test1.Demo {Value = "DEMO"};
ToFile(filename, demo1);
var demo2 = FromFile<Test2.Demo>(filename);
Console.WriteLine(demo2.Value);
}
public static void ToFile(string filename, object obj)
{
DataContractSerializer serializer = new DataContractSerializer(obj.GetType());
using (var streamWriter = File.CreateText(filename))
using (var xmlWriter = XmlWriter.Create(streamWriter, new XmlWriterSettings{Indent = true}))
{
serializer.WriteObject(xmlWriter, obj);
}
}
public static T FromFile<T>(string filename)
{
DataContractSerializer serializer = new DataContractSerializer(typeof(T));
using (var textReader = File.OpenText(filename))
using (var xmlReader = XmlReader.Create(textReader))
{
return (T)serializer.ReadObject(xmlReader);
}
}
[STAThread]
static void Main(string[] args)
{
new Program().run();
}
}
}
If you have already serialized data without the Namespace="" attribute, then you will need instead to apply the appropriate namespace to the new class:
namespace Test1
{
[DataContract]
public sealed class Demo
{
[DataMember]
public string Value { get; set; }
}
}
namespace Test2
{
// Note the namespace includes both nested namespaces, i.e. ConsoleApp1.Test1
[DataContract(Namespace="http://schemas.datacontract.org/2004/07/ConsoleApp1.Test1")]
public sealed class Demo
{
[DataMember]
public string Value { get; set; }
}
}
Given the following class design:
public class AllUserCollections
{
public List<UserCollection> UserCollections { get; set; }
public AllUserCollections()
{
this.UserCollections = new List<UserCollection> ();
}
}
public class UserCollection
{
public string UserGroup { get; set; }
public Dictionary<int,User> Users { get; set; }
public UserCollection(string userGroup)
{
this.UserGroup = userGroup;
this.Users = new Dictionary<int, User> ();
}
}
public class User
{
public int ID { get; set; }
public string Name { get; set; }
public string Location { get; set; }
public AgeGroup UserAgeGroup { get; set; }
}
public enum AgeGroup
{
Twenties,
Thirties,
Fourties,
}
How can I serialize this to XML using my existing serialization class?
public static class HardDriveService
{
private static string docsFolderPath = Environment.GetFolderPath (Environment.SpecialFolder.Personal);
private const string fileName = "AllUserCollections.xml";
private static string filePath = Path.Combine(docsFolderPath, fileName);
private static bool FileExists(string fullFilePath)
{
if (File.Exists (fullFilePath))
return true;
return false;
}
public static void Save(AllUserCollections allUserCollections)
{
if (FileExists(filePath))
{
File.Delete (filePath);
}
XmlSerializer serializer = new XmlSerializer(allUserCollections.GetType());
using(StreamWriter writer = new StreamWriter(filePath))
{
serializer.Serialize(writer.BaseStream, allUserCollections);
}
}
public static AllUserCollections Read()
{
AllUserCollections allUserCollections = new AllUserCollections();
XmlSerializer serializer = new XmlSerializer(allUserCollections.GetType());
if (FileExists(filePath))
{
StreamReader reader = new StreamReader(filePath);
object deserialized = serializer.Deserialize(reader.BaseStream);
allUserCollections = (AllUserCollections)deserialized;
}
return allUserCollections;
}
}//End of class.
ISSUES
My code seems to fail on this line -
XmlSerializer serializer = new XmlSerializer(allUserCollections.GetType());
I wonder if it's to do with the class needing to be explicitly marked as "serializable"? How would I do this?
Usage
This code will run on an iphone and save/read directly from an app to XML on the iPhone hard drive.
XMLSerializer doesn't support Dictionary out of the box. Your UserCollection class has a Dictionary. See this link for a workaround.
Why doesn't XmlSerializer support Dictionary?
Other than that the XMLSerializer requires that your classes have default constructors (UserCollection and User don't) and each of them must have the [Serializable] attribute.
You could use XElement to build up an XML format. You could use them along the following lines:
public static XElement ToXml(this User user)
{
if (user == null)
{
throw new ArgumentException("User can not be null.");
}
XElement userElement = new XElement("User");
userElement.Add(new XElement("ID", user.ID));
userElement.Add(new XElement("Name", user.Name));
userElement.Add(new XElement("Location", user.Location));
userElement.Add(new XElement("UserAgeGroup", user.UserAgeGroup));
return userElement;
}
public static string ToXml(this UserCollection userCollection)
{
if (userCollection == null)
{
throw new ArgumentException("UserCollection can not be null.");
}
XElement userCollectionElement = new XElement("UserCollection");
userCollectionElement.Add(new XElement("UserGroup", userCollection.UserGroup));
userCollectionElement.Add(new XElement("Users",
userCollection.Users.Select(x => new XElement("User", x.ToXml()));
return userCollectionElement;
}
Calling .ToString() on an XElement should give you an xml-formatted string.
FULL WORKING SOLUTION
Data Model
using System;
using System.Collections.Generic;
namespace iPhoneHardDriveCRUDPrototype
{
[Serializable]
public class AllUserCollections
{
public List<UserCollection> UserCollections { get; set; }
public AllUserCollections()
{
this.UserCollections = new List<UserCollection> ();
}
}
[Serializable]
public class UserCollection
{
public string UserGroup { get; set; }
public SerializableDictionary<int,User> Users { get; set; }
public UserCollection()
{
this.Users = new SerializableDictionary<int, User> ();
}
public UserCollection(string userGroup)
{
this.UserGroup = userGroup;
this.Users = new SerializableDictionary<int, User> ();
}
}
[Serializable]
public class User
{
public int ID { get; set; }
public string Name { get; set; }
public string Location { get; set; }
public AgeGroup UserAgeGroup { get; set; }
public User()
{
}
}
[Serializable]
public enum AgeGroup
{
Twenties,
Thirties,
Fourties,
}
}
Serializable Dictionary
using System;
using System.Xml.Serialization;
using System.Collections.Generic;
namespace iPhoneHardDriveCRUDPrototype
{
[XmlRoot("dictionary")]
public class SerializableDictionary<TKey, TValue> : Dictionary<TKey, TValue>, IXmlSerializable
{
public System.Xml.Schema.XmlSchema GetSchema()
{
return null;
}
public void ReadXml(System.Xml.XmlReader reader)
{
XmlSerializer keySerializer = new XmlSerializer(typeof(TKey));
XmlSerializer valueSerializer = new XmlSerializer(typeof(TValue));
bool wasEmpty = reader.IsEmptyElement;
reader.Read();
if (wasEmpty)
return;
while (reader.NodeType != System.Xml.XmlNodeType.EndElement)
{
reader.ReadStartElement("item");
reader.ReadStartElement("key");
TKey key = (TKey)keySerializer.Deserialize(reader);
reader.ReadEndElement();
reader.ReadStartElement("value");
TValue value = (TValue)valueSerializer.Deserialize(reader);
reader.ReadEndElement();
this.Add(key, value);
reader.ReadEndElement();
reader.MoveToContent();
}
reader.ReadEndElement();
}
public void WriteXml(System.Xml.XmlWriter writer)
{
XmlSerializer keySerializer = new XmlSerializer(typeof(TKey));
XmlSerializer valueSerializer = new XmlSerializer(typeof(TValue));
foreach (TKey key in this.Keys)
{
writer.WriteStartElement("item");
writer.WriteStartElement("key");
keySerializer.Serialize(writer, key);
writer.WriteEndElement();
writer.WriteStartElement("value");
TValue value = this[key];
valueSerializer.Serialize(writer, value);
writer.WriteEndElement();
writer.WriteEndElement();
}
}
}//End of Class....
}
Serializer
using System;
using System.IO;
using System.Xml.Serialization;
using System.Reflection;
using System.Collections.Generic;
namespace iPhoneHardDriveCRUDPrototype
{
public static class HardDriveService
{
private static string docsFolderPath = Environment.GetFolderPath (Environment.SpecialFolder.Personal);
private const string fileName = "AllUserCollections.xml";
private static string filePath = Path.Combine(docsFolderPath, fileName);
private static bool FileExists(string fullFilePath)
{
if (File.Exists (fullFilePath))
return true;
return false;
}
public static void Save(AllUserCollections allUserCollections)
{
if (FileExists(filePath))
{
File.Delete (filePath);
}
XmlSerializer serializer = new XmlSerializer(allUserCollections.GetType());
using(StreamWriter writer = new StreamWriter(filePath))
{
serializer.Serialize(writer.BaseStream, allUserCollections);
}
}
public static AllUserCollections Read()
{
AllUserCollections allUserCollections = new AllUserCollections();
XmlSerializer serializer = new XmlSerializer(allUserCollections.GetType());
if (FileExists(filePath))
{
StreamReader reader = new StreamReader(filePath);
object deserialized = serializer.Deserialize(reader.BaseStream);
allUserCollections = (AllUserCollections)deserialized;
}
return allUserCollections;
}
}//End of class.
}
Here you have 2 choices XmlSerializer(which will not work with Dictionary or List type deserialization ) or you can use DataContractSerializer which added in .net 3.0 and has a lot advantages here are few: form this post
optimized for speed (about 10% faster than XmlSerializer, typically)
in "opt-in" - only stuff you specifically mark as [DataMember] will be serialized
doesn't support XML attributes (for speed reasons)
Note : you should add reference to the C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework.NETFramework\v4.0\System.Runtime.Serialization.dll
//to serialize
SerializeHelper.Serialize("your filename" ,new AllUserCollections());
// deserialize
var usertCollections = SerializeHelper.Deserialize<AllUserCollections>("yourfile name");
//code
[DataContract]
public class AllUserCollections
{
public List<UserCollection> UserCollections { get; set; }
public AllUserCollections()
{
this.UserCollections = new List<UserCollection>();
}
}
[DataContract()]
public class UserCollection
{
[DataMember]
public string UserGroup { get; set; }
[DataMember]
public Dictionary<int, User> Users { get; set; }
public UserCollection(string userGroup)
{
this.UserGroup = userGroup;
this.Users = new Dictionary<int, User>();
}
}
[DataContract()]
public class User
{ [DataMember]
public int ID { get; set; }
[DataMember]
public string Name { get; set; }
[DataMember]
public string Location { get; set; }
[DataMember]
public AgeGroup UserAgeGroup { get; set; }
}
[DataContract]
public enum AgeGroup
{
Twenties,
Thirties,
Fourties,
}
public static class SerializeHelper
{
public static void Serialize<T>(string fileName, T obj)
{
using (FileStream writer = new FileStream(fileName, FileMode.Create))
{
DataContractSerializer ser =
new DataContractSerializer(typeof(T));
ser.WriteObject(writer, obj);
writer.Close();
}
}
public static T Deserialize<T>(string fileName)
{
T des;
using (FileStream fs = new FileStream(fileName,FileMode.Open))
{
XmlDictionaryReader reader =
XmlDictionaryReader.CreateTextReader(fs, new XmlDictionaryReaderQuotas());
DataContractSerializer ser = new DataContractSerializer(typeof(T));
des =
(T)ser.ReadObject(reader, true);
reader.Close();
fs.Close();
}
return des;
}
}
I want to serialize like this
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"
xmlns:news="http://www.google.com/schemas/sitemap-news/0.9">
</urlset>
But wrong result generated.
My class is here
[Serializable]
[XmlRoot("urlset")]
public class GoogleSiteMap
{
public GoogleSiteMap() {
xmlns = "http://www.sitemaps.org/schemas/sitemap/0.9";
xmlnsNews = "http://www.google.com/schemas/sitemap-news/0.9";
Urls = new List<gUrlBase>();
}
[XmlAttribute]
public string xmlns { get; set; }
[XmlAttribute("news",Namespace="xmlns")]
public string xmlnsNews { get; set; }
[XmlElement("url")]
public List<gUrlBase> Urls { get; set; }
}
Serializer is here
public static void GenerateGoogle(GoogleSiteMap smap,string filePath) {
XmlSerializer ser = new XmlSerializer(typeof(GoogleSiteMap));
using (FileStream fs = new FileStream(filePath, FileMode.Create))
{
ser.Serialize(fs, smap);
fs.Close();
}
}
Then result is here
<urlset xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:d1p1="xmlns" d1p1:news="http://www.google.com/schemas/sitemap-news/0.9"/>
What's wrong on my class declaration?
Another QUESTION 2
How can i declare like this
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"
xmlns:news="http://www.google.com/schemas/sitemap-news/0.9">
<url>
<loc>http://www.example.org/business/article55.html</loc>
<news:news></news:news>
</url>
<url>
<loc>http://www.example.org/business/page1.html</loc>
<lastmod>2010-10-10</lastmod>
<changefreq>weekly</changefreq>
</url>
</urlset>
my declaration is here
[XmlRoot("urlset", Namespace = "http://www.sitemaps.org/schemas/sitemap/0.9")]
public class GoogleSiteMap
{
public GoogleSiteMap()
{
Urls = new List<gUrlBase>();
}
//[XmlElement("url")]
[XmlElement("url",Type = typeof(gNormalUrl))]
[XmlElement("url",Type = typeof(gNewsUrl))]
public List<gUrlBase> Urls { get; set; }
}
This is return error
The XML element 'url' from namespace 'http://www.sitemaps.org/schemas/sitemap/0.9' is already present in the current scope. Use XML attributes to specify another XML name or namespace for the element.
How can i declare Same root name "url"?
You need to use the right namespace:
[XmlRoot("urlset", Namespace = "http://www.sitemaps.org/schemas/sitemap/0.9")]
you can take away xmlns and xmlnsNews properties - they do something else. Likewise, any data in ""http://www.google.com/schemas/sitemap-news/0.9" will need to be marked as such. Whether the namespace alias is news is irrelevant (it is only an alias), but that can be controlled via XmlSerializerNamespaces if you like. You do not need [Serializable].
For example, if each <url> needs to be in the "http://www.google.com/schemas/sitemap-news/0.9" namespace, and you want to use "http://www.sitemaps.org/schemas/sitemap/0.9" as the overall namespace and "http://www.google.com/schemas/sitemap-news/0.9" aliased as "news", then:
static class Program
{
static void Main()
{
var ns = new XmlSerializerNamespaces();
ns.Add("", "http://www.sitemaps.org/schemas/sitemap/0.9");
ns.Add("news", "http://www.google.com/schemas/sitemap-news/0.9");
var ser = new XmlSerializer(typeof (GoogleSiteMap));
var obj = new GoogleSiteMap {Urls = new List<string> {"abc", "def", "ghi"}};
ser.Serialize(Console.Out, obj, ns);
}
}
[XmlRoot("urlset", Namespace = "http://www.sitemaps.org/schemas/sitemap/0.9")]
public class GoogleSiteMap
{
[XmlElement("url", Namespace = "http://www.google.com/schemas/sitemap-news/0.9")]
public List<string> Urls { get; set; }
}
This generates:
<urlset
xmlns:news="http://www.google.com/schemas/sitemap-news/0.9"
xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<news:url>abc</news:url>
<news:url>def</news:url>
<news:url>ghi</news:url>
</urlset>
(I haven't checked what the actual content namespaces are - this is just to show the relationship between namespaces in the data, namespaces in the xml, and namespace-aliases)
Re your edit - something like:
static class Program
{
static void Main()
{
var ns = new XmlSerializerNamespaces();
ns.Add("", "http://www.sitemaps.org/schemas/sitemap/0.9");
ns.Add("news", "http://www.google.com/schemas/sitemap-news/0.9");
var ser = new XmlSerializer(typeof (GoogleSiteMap));
var obj = new GoogleSiteMap {Urls = {
new SiteUrl { Location = "http://www.example.org/business/article55.html", News = ""},
new SiteUrl { Location = "http://www.example.org/business/page1.html", LastModified = new DateTime(2010,10,10),
ChangeFrequency = "weekly"}
}};
ser.Serialize(Console.Out, obj, ns);
}
}
[XmlRoot("urlset", Namespace = "http://www.sitemaps.org/schemas/sitemap/0.9")]
public class GoogleSiteMap
{
private readonly List<SiteUrl> urls = new List<SiteUrl>();
[XmlElement("url")]
public List<SiteUrl> Urls { get { return urls; } }
}
public class SiteUrl
{
[XmlElement("loc")]
public string Location { get; set; }
[XmlElement("news", Namespace = "http://www.google.com/schemas/sitemap-news/0.9")]
public string News { get; set; }
[XmlElement("lastmod")]
public DateTime? LastModified { get; set; }
[XmlElement("changefreq")]
public string ChangeFrequency { get; set; }
public bool ShouldSerializeLastModified() { return LastModified.HasValue; }
}
which generates:
<urlset xmlns:news="http://www.google.com/schemas/sitemap-news/0.9"
xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<url>
<loc>http://www.example.org/business/article55.html</loc>
<news:news />
</url>
<url>
<loc>http://www.example.org/business/page1.html</loc>
<lastmod>2010-10-10T00:00:00</lastmod>
<changefreq>weekly</changefreq>
</url>
</urlset>
Please use below full code that made by me
Please see below full code
#region GoogleNewsSiteMap Class
[XmlRoot("urlset", Namespace = "http://www.sitemaps.org/schemas/sitemap/0.9")]
public class GoogleNewsSiteMap
{
const string _newsSiteMapSchema = "http://www.google.com/schemas/sitemap-news/0.9";
const string _newsSiteMapPrefix = "n";
public void Create(string loc, string prioity, string language, string name, string genres, string publicationDate, string title)
{
NewsSiteMap news = new NewsSiteMap();
news.Loc = loc;
news.Priority = prioity;
news.NewsSiteMapNews.Publication.Language = language;
news.NewsSiteMapNews.Publication.Name = name;
news.NewsSiteMapNews.Genres = genres;
news.NewsSiteMapNews.PublicationDate = publicationDate;
news.NewsSiteMapNews.Title = title;
List.Add(news);
}
public string GetXMLString()
{
XmlWriterSettings settings = new XmlWriterSettings();
settings.Indent = true;
settings.IndentChars = (" ");
settings.Encoding = new UTF8Encoding(false);
using (StringWriter str = new StringWriter())
using (XmlWriter writer = XmlWriter.Create(str, settings))
{
XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
ns.Add(_newsSiteMapPrefix, _newsSiteMapSchema);
XmlSerializer xser = new XmlSerializer(typeof(GoogleNewsSiteMap));
xser.Serialize(writer, this, ns);
return str.ToString();
}
}
private List<NewsSiteMap> _list = null;
[XmlElement("url")]
public List<NewsSiteMap> List
{
get
{
if (_list == null)
{
_list = new List<NewsSiteMap>();
}
return _list;
}
}
#region NewsSiteMap Class
public class NewsSiteMap
{
private string _loc = string.Empty;
private string _priority = string.Empty;
private NewsSiteMap_News _newsSiteMap_News = null;
[XmlElement("loc")]
public string Loc
{
get { return _loc; } set { _loc = value; }
}
[XmlElement("priority")]
public string Priority
{
get { return _priority; } set { _priority = value; }
}
[XmlElement("news", Namespace = _newsSiteMapSchema)]
public NewsSiteMap_News NewsSiteMapNews
{
get {
if (_newsSiteMap_News == null)
{
_newsSiteMap_News = new NewsSiteMap_News();
}
return _newsSiteMap_News;
}
set { _newsSiteMap_News = value; }
}
#region NewsSiteMap_News Class
public class NewsSiteMap_News
{
private NewsSiteMap_Publication _publication = null;
private string _genres = string.Empty;
private string _publicationDate = string.Empty;
private string _title = string.Empty;
private string _keywords = string.Empty;
private string _stockTickers = string.Empty;
[XmlElement("publication", Namespace = _newsSiteMapSchema)]
public NewsSiteMap_Publication Publication
{
get
{
if (_publication == null)
{
_publication = new NewsSiteMap_Publication();
}
return _publication;
}
set { _publication = value; }
}
[XmlElement("genres")]
public string Genres
{
get { return _genres; }
set { _genres = value; }
}
[XmlElement("publication_date")]
public string PublicationDate
{
get
{
try
{
return string.Format("{0:s}", Convert.ToDateTime(_publicationDate)) + string.Format("{0:zzz}", Convert.ToDateTime(_publicationDate));
}
catch (Exception ex)
{
return _publicationDate;
}
}
set { _publicationDate = value; }
}
public string Title
{
set { _title = value; }
}
[XmlElement("title")]
public XmlCDataSection CTitle
{
get
{
XmlDocument doc = new XmlDocument();
return doc.CreateCDataSection(_title);
}
set { _title = value.Value; }
}
[XmlElement("keywords")]
public string Keywords
{
get { return _keywords; } set { _keywords = value; }
}
[XmlElement("stock_tickers")]
public string StockTickers
{
get { return _stockTickers; } set { _stockTickers = value; }
}
#region NewsSiteMap_Publication Class
public class NewsSiteMap_Publication
{
private string _name = string.Empty;
private string _language = string.Empty;
[XmlElement("name")]
public string Name
{
get { return _name; }
set { _name = value; }
}
[XmlElement("language")]
public string Language
{
get { return _language; }
set { _language = value; }
}
}
#endregion NewsSiteMap_Publication Class
}
#endregion NewsSiteMap_News Class
}
#endregion NewsSiteMap Class
}
#endregion GoogleNewsSiteMap Class
Usage
Response.Clear();
Response.ContentType = "text/xml";
Response.ContentEncoding = System.Text.Encoding.UTF8;
GoogleNewsSiteMap googleNewsSiteMap = new GoogleNewsSiteMap();
googleNewsSiteMap.Create(/*put ur data*/);
Response.Write(googleNewsSiteMap.GetXMLString());