I want to create object that after serialize to xml should looks like:
<List>
<Map>
<Entry Key="1" Value="ASD" />
</Map>
<Map>
<Entry Key="2" Value="DFE" />
</Map>
</List>
Instead of this my result is:
<List>
<Map>
<Entry Key="1" Value="ASD" />
<Entry Key="2" Value="DFE" />
</Map>
</List>
My piece of code:
public partial class List {
private Map[] mapField;
[System.Xml.Serialization.XmlArrayAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
[System.Xml.Serialization.XmlArrayItemAttribute("Entry", typeof(Map), Form=System.Xml.Schema.XmlSchemaForm.Unqualified, IsNullable=false)]
public Map[] Map {
get {
return this.mapField;
}
set {
this.mapField = value;
}
}
public partial class MapTypeEntry
{
private string keyField;
private string valueField;
[System.Xml.Serialization.XmlAttributeAttribute()]
public string Key {
get {
return this.keyField;
}
set {
this.keyField = value;
}
}
[System.Xml.Serialization.XmlAttributeAttribute()]
public string Value {
get {
return this.valueField;
}
set {
this.valueField = value;
}
}
}
What I'm doing wrong?
I think I did typo somewhere, but I can't find where.
Maybe there is problem with xml attributes?
Maytbe this shouldn't be xmlArray item?
EDIT:
Complete code:
var mapEntry = new Map();
mapEntry.Key = "1";
mapEntry.Value = "ASD";
mapEntries.Add(mapEntry);
mapEntry = new Map();
mapEntry.Key = "2";
mapEntry.Value = "DFE";
mapEntries.Add(mapEntry);
var exampleType = new List();
List.Map = mapEntries.ToArray();
You need to change model as I implemented below (just simple exmple).
namespace TestApp
{
using System;
using System.IO;
using System.Xml.Schema;
using System.Xml.Serialization;
class Program
{
static void Main(string[] args)
{
var list = new List
{
Map = new[]
{
new Entry {EntryItem = new EntryItem {Key = "1", Value = "ASD"}},
new Entry {EntryItem = new EntryItem {Key = "2", Value = "DFE"}}
}
};
Console.Write(Serialize(list));
Console.ReadKey();
}
private static string Serialize(List list)
{
var xmlSerializer = new XmlSerializer(typeof (List));
var stringWriter = new StringWriter();
xmlSerializer.Serialize(stringWriter, list);
return stringWriter.ToString();
}
}
[XmlRoot(ElementName = "Root")]
public partial class List
{
[XmlArray(ElementName = "List")]
[XmlArrayItem("Map", typeof (Entry), Form = XmlSchemaForm.Unqualified, IsNullable = false)]
public Entry[] Map { get; set; }
}
public class Entry
{
[XmlElement("Entry")]
public EntryItem EntryItem { get; set; }
}
public class EntryItem
{
[XmlAttribute]
public string Key { get; set; }
[XmlAttribute]
public string Value { get; set; }
}
}
So it creates XML:
<?xml version="1.0" encoding="utf-16"?>
<Root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<List>
<Map>
<Entry Key="1" Value="ASD" />
</Map>
<Map>
<Entry Key="2" Value="DFE" />
</Map>
</List>
</Root>
Here's what your class List should look :
public partial class List
{
private Map[] mapField;
[XmlElement("Map", typeof(Map), Form = System.Xml.Schema.XmlSchemaForm.Unqualified, IsNullable = false)]
public Map[] Map
{
get
{
return this.mapField;
}
set
{
this.mapField = value;
}
}
[...]
}
And for your Map class
public class Map
{
[XmlElement("Entry")]
public KVPair Item { get; set; }
}
And the one I called KVPair
public class KVPair
{
[XmlAttribute()]
public string Key { get; set; }
[XmlAttribute()]
public string Value { get; set; }
}
the Xml Produced is :
<?xml version="1.0"?>
<List xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Map>
<Entry Key="1" Value="ASD" />
</Map>
<Map>
<Entry Key="2" Value="DFE" />
</Map>
</List>
You should avoid using class name frequently used such as List. If you want to call it with a different name, use XmlRootAttribute to keep "List" for your xml file.
Related
Here is my two classes: the class Characteristic and Definition :
[DataContract]
public class Characteristic
{
[DataMember]
public Definition Definition { get; set; }
}
[Serializable]
public class Definition
{
[XmlAttribute]
public int id;
[XmlAttribute]
public stringName;
}
and this is my implementation :
Characteristic lstChars = new Characteristic()
{
Definition = new Definition()
{
id = Dimension.ID,
name = Dimension.Name
}
};
I get this result:
<Characteristic>
<Definition>
<id>6</id>
<name>ACTIVITY</name>
</Definition>
And my objectif is to get this result:
<Characteristic>
<Definition id="6" Name= "ACTIVITY" />
In order to serialize it, you can use the following ways:
To serialize it into a string:
string result;
using (var writer = new StringWriter())
{
new XmlSerializer(typeof(Characteristic)).Serialize(writer, lstChars);
result = writer.ToString();
}
To serialize and store it on a file:
using (var writer = new StreamWriter(xmlFilePath))
{
new XmlSerializer(typeof(Characteristic)).Serialize(writer, lstChars);
}
I am getting the following error in my Xamarin Forms app but I don't know what the problem is:
System.InvalidOperationException: There is an error in XML document.
items xmlns=''> was not expected
I have a basic XML file that I have added as an embedded resource:
<?xml version="1.0" encoding="UTF-8"?>
<items>
<item>
<id>1</id>
<name>a name</name>
<address>an address</address>
<postcode>a postcode</postcode>
</item>
<item>
<id>2</id>
<name>name 2</name>
<address>address 2</address>
<postcode>postcode 2</postcode>
</item>
<item>
<id>3</id>
<name>name 3</name>
<address>address 3</address>
<postcode>postcode 3</postcode>
</item>
</items>
I have the following method to read the XML file:
public static List<Item> GetItemList()
{
var assembly = typeof(MyNewPage).GetTypeInfo().Assembly;
Stream stream = assembly.GetManifestResourceStream("MyNewApp.allitems.xml");
List<Item> itemsFullList;
using (var reader = new System.IO.StreamReader(stream))
{
var serializer = new XmlSerializer(typeof(List<Item>));
itemsFullList = (List<Item>)serializer.Deserialize(reader);
}
return itemsFullList;
}
I also have a standard class to represent each item:
public class Item
{
public Item()
{
}
public string name { get; set; }
public string address { get; set; }
public string postcode { get; set; }
}
I don't know why I am getting the error as from what I can see, the XML document is formatted just fine. I am using this article as a guide but I am having no luck: https://developer.xamarin.com/guides/xamarin-forms/application-fundamentals/files/
Anyone know what I am doing wrong here?
Thanks.
That class structure will not deserialize to a list of Item, it will deserialize to a single object that has a property of type Item[].
You will probably want to change class and property names to make more sense, but this is how Visual Studio generates the class structure based on your xml (Edit > Paste Special)
void Main()
{
string xml = #"<?xml version=""1.0"" encoding=""UTF-8""?>
<items>
<item>
<id>1</id>
<name>a name</name>
<address>an address</address>
<postcode>a postcode</postcode>
</item>
<item>
<id>2</id>
<name>name 2</name>
<address>address 2</address>
<postcode>postcode 2</postcode>
</item>
<item>
<id>3</id>
<name>name 3</name>
<address>address 3</address>
<postcode>postcode 3</postcode>
</item>
</items>";
using (MemoryStream ms = new MemoryStream())
{
XDocument.Parse(xml).Save(ms);
ms.Position = 0;
using (var reader = new System.IO.StreamReader(ms))
{
var serializer = new XmlSerializer(typeof(items));
var itemsFullList = (items)serializer.Deserialize(reader);
}
}
}
/// <remarks/>
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
[System.Xml.Serialization.XmlRootAttribute(ElementName = "items", Namespace = "", IsNullable = false)]
public partial class items
{
private itemsItem[] itemField;
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute("item")]
public itemsItem[] item
{
get
{
return this.itemField;
}
set
{
this.itemField = value;
}
}
}
/// <remarks/>
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
public partial class itemsItem
{
private byte idField;
private string nameField;
private string addressField;
private string postcodeField;
/// <remarks/>
public byte id
{
get
{
return this.idField;
}
set
{
this.idField = value;
}
}
/// <remarks/>
public string name
{
get
{
return this.nameField;
}
set
{
this.nameField = value;
}
}
/// <remarks/>
public string address
{
get
{
return this.addressField;
}
set
{
this.addressField = value;
}
}
/// <remarks/>
public string postcode
{
get
{
return this.postcodeField;
}
set
{
this.postcodeField = value;
}
}
}
I have a c# project that serializes a list of objects out to xml.
[Serializable]
[XmlRoot]
public class collection {
private List<item> _items = new List<item>();
[XmlElement("item")]
public List<item> items {
get { return _items; }
}
}
[Serializable]
public class item {
}
the xml output is then
<collection>
<item/>
<item/>
<item/>
</collection>
what I would like is to add the option of folders&subfolders so items can be grouped together while still being able to go in the root node.
<collection>
<item/>
<item/>
<folder>
<item/>
<item/>
</folder>
<item/>
<item/>
<folder>
<item/>
<item/>
<folder>
<item/>
<item/>
</folder>
</folder>
<item/>
</collection>
Can anyone advise a clean way of doing this while continuing to generate the xml output using serialised objects?
This has to be the class structure.
public class Folder2
{
}
public class Folder
{
public Folder2 folder { get; set; }
}
public class Collection
{
public List<Folder> folder { get; set; }
}
public class RootObject
{
public Collection collection { get; set; }
}
After a bit of trial and error I managed to get the functionality I was after.
[Serializable]
[XmlRoot]
public class collection {
private List<treeEntry> _entries = new List<treeEntry>();
[XmlElement("item", typeof(item))]
[XmlElement("folder", typeof(folder))]
public List<treeEntry> entries {
get { return _entries; }
}
}
public abstract class treeEntry { }
[Serializable]
public class folder : treeEntry {
private List<treeEntry> _entries = new List<treeEntry>();
public folder() { }
[XmlAttribute]
public string name { get; set; }
[XmlElement("item", typeof(item))]
[XmlElement("folder", typeof(folder))]
public List<treeEntry> entries {
get { return _entries; }
}
}
[Serializable]
public class item : treeEntry { }
public class mytest {
public static void main() {
collection col = new collection();
col.entries.Add(new item());
col.entries.Add(new item());
var folder1 = new folder() { name = "someFolder" };
folder1.entries.Add(new item());
var folder2 = new folder() { name = "anotherFolder" };
folder1.entries.Add(folder2);
folder1.entries.Add(new item());
folder2.entries.Add(new item());
col.entries.Add(folder1);
col.entries.Add(new folder());
col.entries.Add(new item());
XmlSerializer sers = new XmlSerializer(typeof(collection));
//serialise
using (StreamWriter sw = new StreamWriter("testoutput.xml", false, Encoding.UTF8)) {
XmlWriter xw = new XmlTextWriter(sw);
sers.Serialize(xw, col);
}
//deserialise
FileStream fs = new FileStream("testoutput.xml", FileMode.Open);
XmlReader reader = XmlReader.Create(fs);
collection newcol = (collection)sers.Deserialize(reader);
//output to console
sers.Serialize(Console.Out, newcol);
}
}
which produced the desired output
<collection>
<item />
<item />
<folder name="someFolder">
<item />
<folder name="anotherFolder">
<item />
</folder>
<item />
</folder>
<folder />
<item />
</collection>
The XML is generated and loaded by the same .NET with c# desktop application using XMLSerialize serialization / deserialization.
The serializable class structur is quiet complex, so I just made a selection of the two relevant classes.
Now, when I deserialize, everything is loaded except the Mapping Messages (or Messages as how the object list is called in the Organization.
Does anyone have an explanation for this behaviour?
Any tips or hints for improving what has already been made are also always appreciated.
Thank you.
I have the following XML:
<?xml version="1.0" encoding="utf-8"?>
<configuration xmlns:xsd="Company.Test3.Crm.Crm2Queue.Config.xsd">
<organizations>
<organization name="Vanilla">
<settings>
<ignoreemptyfields>true</ignoreemptyfields>
<throwerroronmissingconfiguration>true</throwerroronmissingconfiguration>
</settings>
<endpoints>
<endpoint>
<serviceUri>http://www.webservicex.net/usaddressverification.asmx</serviceUri>
</endpoint>
</endpoints>
<messages>
<message name="account">
<field name="accountnumber" mappedname="State" />
<field name="address1_county" mappedname="Zip" />
<field name="address1_latitude" mappedname="City" />
</message>
</messages>
<entities>
<entity name="account" messageschema="/XSD/.xsd" identifier="accountid">
<events>
<event name="create" message="" />
<event name="update" message="" />
<event name="delete" message="" />
</events>
</entity>
</entities>
</organization>
</organizations>
</configuration>
Now the serializable class looks as following:
[Serializable()]
public class Organization
{
#region XmlIgnore
[XmlIgnore()]
public string Id { get; set; }
[XmlIgnore()]
public bool Checked { get; set; }
[XmlIgnore()]
public List<MappingMessage> mappingMessages { get; set; }
#endregion
#region Attributes
[XmlAttribute("name")]
public string Name { get; set; }
#endregion
#region Properties
[XmlElement("settings")]
public Settings Settings { get; set; }
public bool ShouldSerializeSettings() { return (Settings != null && (Settings.IgnoreEmptyFields.HasValue || Settings.ThrowErrorOnMissingConfiguration.HasValue)); }
[XmlArray("endpoints")]
[XmlArrayItem("endpoint")]
public List<Endpoint> Endpoints { get; set; }
public bool ShouldSerializeignoreEndpoints() { return (Endpoints.Count > 0); }
[XmlArray("messages")]
[XmlArrayItem("message")]
public List<MappingMessage> Messages
{
get { return mappingMessages.Where(mm => (mm.Fields.Where(fi => !string.IsNullOrEmpty(fi.MappedName)).ToList().Count > 0)).ToList(); }
set { mappingMessages = value; }
}
public bool ShouldSerializeFilledMappingMessages() { return (mappingMessages.Where(mm => (mm.Fields.Where(fi => !string.IsNullOrEmpty(fi.MappedName)).ToList().Count > 0)).ToList().Count > 0); }
//public bool ShouldSerializeMappingMessages() { return (MappingMessages.Where(mm=> (mm.Fields.Where(fi=> !string.IsNullOrEmpty(fi.MappedName)).ToList().Count > 0)).ToList().Count > 0); }
[XmlArray("entities")]
[XmlArrayItem("entity")]
public List<Entity> Entities { get; set; }
public bool ShouldSerializeEntities() { return (Entities.Count > 0); }
#endregion
#region Constructors
public Organization()
{
Settings = new Settings();
Endpoints = new List<Endpoint>();
mappingMessages = new List<MappingMessage>();
Entities = new List<Entity>();
Checked = false;
}
public Organization(string name)
: this()
{
Name = name;
}
public Organization(string id, string name)
: this(name)
{
Id = id;
}
#endregion
}
[Serializable()]
public class MappingMessage
{
#region XmlIgnore
[XmlIgnore()]
public string EntityId { get; set; }
[XmlIgnore()]
public bool Checked { get; set; }
[XmlIgnore()]
public List<Field> Fields { get; set; }
#endregion
#region Attributes
[XmlAttribute("id")]
public string Id { get; set; }
[XmlAttribute("name")]
public string Name { get; set; }
#endregion
#region Properties
[XmlElement("field")]
public List<Field> SelectedFields
{
get
{
return Fields.Where(fi=> !string.IsNullOrEmpty(fi.MappedName)).ToList();
}
set
{
Fields = value;
}
}
public bool ShouldSerializeSelectedFields() { return (SelectedFields.Count > 0); }
[XmlElement("subentity")]
public List<SubEntity> SubEntities { get; set; }
public bool ShouldSerializeSubEntities() { return (SubEntities.Count > 0); }
[XmlElement("parententity")]
public List<ParentEntity> ParentEntities { get; set; }
public bool ShouldSerializeParentEntities() { return (ParentEntities.Count > 0); }
#endregion
#region Constructors
public MappingMessage()
{
Checked = false;
Fields = new List<Field>();
SubEntities = new List<SubEntity>();
ParentEntities = new List<ParentEntity>();
}
public MappingMessage(string entityId)
: this()
{
EntityId = entityId;
}
public MappingMessage(string entityId, string name)
: this(entityId)
{
Name = name;
}
#endregion
}
And I use deserialization as shown below:
foreach (ZipEntry zipEntry in zipFile)
{
using (MemoryStream memoryStream = new MemoryStream())
{
if (zipEntry.FileName.ToLower().EndsWith(".crm.crm2queue.config.xml"))
{
using (StreamReader streamReader = new StreamReader(memoryStream, Encoding.UTF8))
{
zipEntry.Extract(memoryStream);
memoryStream.Position = 0;
XmlSerializer xmlSerializer = new XmlSerializer(typeof(Ciber.Crm.MappingCRMTo.Data.Configuration));
configuration = (Configuration)xmlSerializer.Deserialize(streamReader);
}
}
}
}
The deserializer tries to fill the list returnepublic List<MappingMessage> Messages. In order to the serializer invoke the setter, you must change the property type to an immutable collection type, say MappingMessage[].
Edit : to see that, you can replace the Entities auto-property by a property with backing field, and set a breakpoint in both getter and setter. You should not break in the setter, only in the getter.
so i have this problem i`m trying to serialize my classes to the point that they will look like this:
<orders>
<order>
<ordersID>22070</ordersID>
<ordersTotal>53.00</ordersTotal>
<prod>
<productCount>1</productCount>
<productPrice>2.00</productPrice>
<productPricePromo>0.00</productPricePromo>
<productDiscount>0</productDiscount>
<productName>Шампоан против косопад Loreal Density Advanced 500 мл.</productName>
<productNumber>30055</productNumber>
</prod>
<prod>
<productCount>1</productCount>
<productPrice>6.00</productPrice>
<productPricePromo>0.00</productPricePromo>
<productDiscount>0</productDiscount>
<productName>Маска за суха коса Loreal Интенс Рипер 200 мл.</productName>
<productNumber>30107</productNumber>
</prod>
</order>
</orders>
But whatever i try e end up like this:
<?xml version="1.0" encoding="UTF-8"?>
<orders xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<order>
<order>
<ordersID>0</ordersID>
<ordersTotal>0</ordersTotal>
<products>
<progducts>
<productCount>0</productCount>
<productPrice>0</productPrice>
<productPricePromo>0</productPricePromo>
<productDiscount>0</productDiscount>
<productNumber>0</productNumber>
</progducts>
<progducts>
<productCount>0</productCount>
<productPrice>0</productPrice>
<productPricePromo>0</productPricePromo>
<productDiscount>0</productDiscount>
<productNumber>0</productNumber>
</progducts>
</products>
</order>
</order>
</orders>
The problem is the names of the second and third class i`m using is geting listed as tags aswell inside the xml. So my question is: is there any way around this?
Here is my code aswell.
Classes:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Serialization;
namespace testXML
{
[Serializable]
public class orders
{
private List <order> m_order = new List <order>();
[XmlArrayItem(typeof(order))]
public List<order> order
{
get { return m_order; }
set { m_order = value; }
}
}
[Serializable]
public class order
{
public int ordersID { get; set; }
public double ordersTotal { get; set; }
private List<progducts> prod = new List<progducts>();
[XmlArrayItem(typeof(progducts))]
public List<progducts> products
{
get { return prod; }
set { prod = value; }
}
}
[Serializable]
public class progducts
{
public string productName { get; set; }
public int productCount { get; set; }
public double productPrice { get; set; }
public double productPricePromo { get; set; }
public double productDiscount { get; set; }
public Int64 productNumber { get; set; }
}
}
And here is the execution code:
orders f = new orders();
order or = new order();
progducts p1 = new progducts();
progducts p2 = new progducts();
f.order.Add(or);
or.products.Add(p1);
or.products.Add(p2);
XmlSerializer xmlSerializer = new XmlSerializer(typeof(orders));
TextWriter writer = new StreamWriter("Family.xml");
xmlSerializer.Serialize(writer, f);
writer.Close();
Thank you for any help in advance!
Replace the [XmlArrayItem(typeof(order))] with [XmlElement("order")] and [XmlArrayItem(typeof(progducts))] with [XmlElement("prod")]. That will remove one level when serializing the lists.
Just add another attributes to your property order like this:
[XmlArray("orders")]
[XmlArrayItem("order", typeof(order))]
public List<order> order
{
get { return m_order; }
set { m_order = value; }
}
That should work.
If you use the following classes which were generated using xsd.exe:
using System.Xml.Serialization;
using System;
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)]
[System.Xml.Serialization.XmlRootAttribute(Namespace="", IsNullable=false)]
public partial class orders
{
private ordersOrder orderField;
public ordersOrder order
{
get
{
return this.orderField;
}
set
{
this.orderField = value;
}
}
}
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)]
public partial class ordersOrder
{
private int ordersIDField;
private double ordersTotalField;
private ordersOrderProd[] prodField;
public int ordersID
{
get
{
return this.ordersIDField;
}
set
{
this.ordersIDField = value;
}
}
public double ordersTotal
{
get
{
return this.ordersTotalField;
}
set
{
this.ordersTotalField = value;
}
}
[System.Xml.Serialization.XmlElementAttribute("prod")]
public ordersOrderProd[] prod
{
get
{
return this.prodField;
}
set
{
this.prodField = value;
}
}
}
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)]
public partial class ordersOrderProd
{
private int productCountField;
private double productPriceField;
private double productPricePromoField;
private double productDiscountField;
private string productNameField;
private Int64 productNumberField;
public int productCount
{
get
{
return this.productCountField;
}
set
{
this.productCountField = value;
}
}
public double productPrice
{
get
{
return this.productPriceField;
}
set
{
this.productPriceField = value;
}
}
public double productPricePromo
{
get
{
return this.productPricePromoField;
}
set
{
this.productPricePromoField = value;
}
}
public double productDiscount
{
get
{
return this.productDiscountField;
}
set
{
this.productDiscountField = value;
}
}
public string productName
{
get
{
return this.productNameField;
}
set
{
this.productNameField = value;
}
}
public Int64 productNumber
{
get
{
return this.productNumberField;
}
set
{
this.productNumberField = value;
}
}
}
Then the following code:
var orders = new orders
{
order = new ordersOrder
{
ordersID = 1,
ordersTotal = 1,
prod = new ordersOrderProd[]
{
new ordersOrderProd
{
productCount = 1,
productDiscount = 8.4,
productName = "Widget",
productNumber = 987987,
productPrice = 78.9,
productPricePromo = 68.75
}
}
}
};
XmlSerializer xmlSerializer = new XmlSerializer(typeof(orders));
TextWriter writer = new StreamWriter(".\\Family.xml");
xmlSerializer.Serialize(writer, orders);
writer.Close();
Gives you the following output:
<?xml version="1.0" encoding="utf-8"?>
<orders xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<order>
<ordersID>1</ordersID>
<ordersTotal>1</ordersTotal>
<prod>
<productCount>1</productCount>
<productPrice>78.9</productPrice>
<productPricePromo>68.75</productPricePromo>
<productDiscount>8.4</productDiscount>
<productName>Widget</productName>
<productNumber>987987</productNumber>
</prod>
</order>
</orders>
You can use a serialization attribute to change the names of the XML elements or attributes you want to represent your class structure. See MSDN