During de-serialization, how do I ignore a property? In my case, I don't want the FullName property to get initialized at all. I am not looking for [XMLIgnore] solutions - think it as a scenario where I don't have access to change the class.
Here's my class:
public class Person
{
public int Id { get; set; }
public string FullName { get; set; }
}
Here's how I am initializing:
Person p1 = new Person() { Id = 1, FullName = "P1" };
Person p2 = new Person() { Id = 2, FullName = "P2" };
List<Person> persons = new List<Person> { p, q }; //this object is xml serialized.
And here's my XML: ( I got it though the XML Serialization)
<?xml version="1.0" encoding="utf-8"?>
<ArrayOfPerson xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Person>
<Id>1</Id>
<FullName>P1</FullName>
</Person>
<Person>
<Id>2</Id>
<FullName>P2</FullName>
</Person>
</ArrayOfPerson>
You can use a custom XmlReader in the deserialization process that will simply skip over the FullName elements. Something like this:
public class MyXmlReader : XmlTextReader
{
public MyXmlReader(string filePath) : base(filePath)
{
}
public override bool Read()
{
if (base.Read())
{
if (Name == "FullName")
return base.Read();
return true;
}
return false;
}
}
Then use it like this
var serializer = new XmlSerializer(typeof(List<Person>));
using (var reader = new MyXmlReader("XMLFile.xml"))
{
var person = (List<Person>)serializer.Deserialize(reader);
}
You can implement a different constructor to take a stream or whatever you have. It doesn't have to be a file path.
Related
I try to read from an xml file, but its very clonky and a lot of the data I get is in bunch from a child. I get the Name, Age, and so on in one and therefor I can't add it to a list.
My xml-file looks like this:
<?xml version="1.0" encoding="UTF-8"?><People>
<Person>
<Age>30</Age>
<Name>Boy</Name>
<Sex>Male</Sex>
</Person>
<Person>
<Age>28</Age>
<Name>Girl</Name>
<Sex>Female</Sex>
</Person>
And in my xaml.cs file I have:
List<listTest> a = new List<listTest>();
var localFolder = ApplicationData.Current.LocalFolder;
XmlDocument xmlDocument;
var file = await localFolder.TryGetItemAsync("FoodData.xml") as IStorageFile;
xmlDocument = await XmlDocument.LoadFromFileAsync(file);
And with that I need to make a setup where I can take data from the XML and put it into list<> like this:
a.add(listTest {Name = "*DATA FROM XML*", Age ="*DATA FROM XML*", Sex="*DATA FROM XML*"});
I have tried to use LINQ and use p.NodeName == "xxx" to make searches, but I don't seem to get any data out.
Can some one show me how to get the data from my xml to a list?
Let's assume you have this class:
public class Person
{
public string Name { get; set; }
public string Sex { get; set; }
public int Age { get; set; }
}
Then, to load your XML file, you could do something like:
var doc = XDocument.Load("path to your file");
var people = doc.Root
.Descendants("person")
.Select(node => new Person
{
Name = node.Element("name").Value,
Sex = node.Element("sex").Value,
Age = int.Parse(node.Element("age").Value)
})
.ToList();
See https://msdn.microsoft.com/en-us/library/bb353813.aspx
Here is a simple example of an XML import. After this code executes, results will reflect if people were found (true or false), and msg will be a list of error messages (or empty if success).
var results = true;
var msg = new List<string>(0);
XDocument aDocument = null;
try
{
aDocument = XDocument.Load("");
}
catch (Exception e)
{
results = false;
msg.Add(string.Format("Unable to open file:{0}", ""));
msg.Add(e.Message);
}
if (aDocument != null)
{
var thePeople = aDocument.Descendants("Person").ToArray();
if (thePeople.Any())
{
// there were people in the file. People is an array of XML Nodes containing your person.
foreach (var pers in thePeople.Select(p => new Person().FromXML(p)))
{
// here is a person
}
}
else
{
results = false;
msg.Add("No people found.");
}
}
Hope this helps.
Addition.
You could do something like this in your Person Class. I've added code to the original to illustrate usage.
public class Person
{
public string Name { get; set; }
public int Age { get; set; }
public string Sex { get; set; }
public XElement ToXML()
{
return new XElement("Person", "Name", Name,
new XElement("Age", Age),
new XElement("Sex", Sex));
}
public Person FromXML(XElement node)
{
try { Name = node.Element("Name").Value; }
catch { Name = "Not Found"; }
try { Age = Convert.ToInt16(node.Element("Age").Value); }
catch { Age = -1; }
try { Sex = node.Element("Sex").Value; }
catch { Sex = ""; }
return this;
}
}
I'm looking to bind XML to Model in C# MVC app.
XML:
<people>
<person>
<name>Mr Brown</name>
<age>40</age>
<hobby>
<title>Eating</title>
<description>eats a lot</description>
</hobby>
<hobby>
<title>Sleeping</title>
<description>sleeps a lot</description>
</hobby>
</person>
<person>
<name>Mr White</name>
<age>40</age>
<hobby>
<title>Skiing</title>
<description>more details on this</description>
</hobby>
<hobby>
<title>Football</title>
<description>watches football</description>
</hobby>
</person>
</people>
Model:
public class People
{
public string Name { get; set; }
public string Age { get; set; }
public IList<Hobbies> Hobby {get; set; }
}
public class Hobbies
{
public string Title { get; set; }
public string Description { get; set; }
}
Broken Binding:
var person = from a in xml.Descendants("person")
select new People
{
Name = a.Element("name").Value,
Age = a.Element("age").Value,
Hobby = *WHAT GOES HERE?*
}
I'n new to C# and looking for the best way to bind the data from the XML to the person var. Which I'll later loop over and output in an HTML table.
Any help would be great.
You have to do it this way:
var person = from a in xml.Descendants("person")
select new People
{
Name = a.Element("name").Value,
Age = a.Element("age").Value,
Hobby = a.Descendants("hobby")
.Select(x=> new Hobbies
{
Title =x.Element("title").Value,
Description = x.Element("description").Value
}).ToList()
};
WORKING FIDDLE:
https://dotnetfiddle.net/2uKdd5
Looks like you want standard XML deserialization. Some good answers on the best way to do that here
I would use XmlSerializer to load from Xml and to save to xml.
You can derive People from this class for example (SerializeManagement) :
public class SerializeManagement<T>
{
public static T ReadFromXML(string iPath)
{
T val = default(T);
try
{
// load from XML
using (var sw = new StreamReader(iPath, Encoding.Default))
{
var ser = new XmlSerializer(typeof(T));
val = (T)ser.Deserialize(sw);
}
}
catch
{
Console.WriteLine("Problem reading from xml data file.");
}
return val;
}
public void SaveToXML(string iPath)
{
try
{
//TODO => using
var sw = new StreamWriter(iPath, false, Encoding.Default);
var ser = new XmlSerializer(typeof(T));
ser.Serialize(sw, this);
sw.Close();
}
catch
{
Console.WriteLine("Problem saving to xml data file.");
}
}
}
If you encounter problems, this could be because of your model definition or xml structure :
Then you can :
1) Generate c# class from the xml using xsd utility;
2) Generate XML from existing class using SaveToXML. That way you are sure the XML structure is compliant with your model.
Enjoy !
I have class like this below shown. which contains the shopping items where the number can vary from 0 to n.
namespace SerializationPOC
{
public class ShoppingItems
{
public string CustomerName { get; set; }
public string Address { get; set; }
public List<Item> Items { get; set; }
}
public class Item
{
public string Name { get; set; }
public string Price { get; set; }
}
}
Is it possible to get the class serialized like to get the XML Schema like below.
<?xml version="1.0" encoding="utf-8" ?>
<ShoppingItems>
<CustomerName>John</CustomerName>
<Address>Walstreet,Newyork</Address>
<Item1>Milk</Item1>
<Price1>1$</Price1>
<Item2>IceCream</Item2>
<Price2>1$</Price2>
<Item3>Bread</Item3>
<Price3>1$</Price3>
<Item4>Egg</Item4>
<Price4>1$</Price4>
<Item..n>Egg</Item..n>
<Price..n>1$</Price..n>
</ShoppingItems>
I would like to know if this can be achieved by using the Serilization if not whats the best way to achieve this Schema?
There is no standard serializer that supports that layout. You will have to do it yourself. Personally, I would say "you're doing it wrong"; I strongly suggest (if it is possible) using a format like
<Item name="IceCream" Price="1$"/>
or
<Item><Name>IceCream</Name><Price>1$</Price></Item>
both of which would be trivial with XmlSerializer.
LINQ-to-XML is probably your best option, something like:
var items = new ShoppingItems
{
Address = "Walstreet,Newyork",
CustomerName = "John",
Items = new List<Item>
{
new Item { Name = "Milk", Price = "1$"},
new Item { Name = "IceCream", Price = "1$"},
new Item { Name = "Bread", Price = "1$"},
new Item { Name = "Egg", Price = "1$"}
}
};
var xml = new XElement("ShoppingItems",
new XElement("CustomerName", items.CustomerName),
new XElement("Address", items.Address),
items.Items.Select((item,i)=>
new[] {
new XElement("Item" + (i + 1), item.Name),
new XElement("Price" + (i + 1), item.Price)}))
.ToString();
Can you please have a look on my article, [^]
As an example you can look into the below code. The Serialize method is given on the article.
var test = new ShoppingItems()
{
CustomerName = "test",
Address = "testAddress",
Items = new List<Item>()
{
new Item(){ Name = "item1", Price = "12"},
new Item(){Name = "item2",Price = "14"}
},
};
var xmlData = Serialize(test);
And it will return the string given below,
<?xml version="1.0" encoding="utf-16"?>
<ShoppingItems xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<CustomerName>test</CustomerName>
<Address>testAddress</Address>
<Items>
<Item>
<Name>item1</Name>
<Price>12</Price>
</Item>
<Item>
<Name>item2</Name>
<Price>14</Price>
</Item>
</Items>
</ShoppingItems>
I've got this XML;
<ChartXml>
<Category type="xAxis">
<Value>Mon</Value>
<Value>Tue</Value>
<Value>Wed</Value>
<Value>Thurs</Value>
<Value>Friday</Value>
</Category>
</ChartXml>
And this class structure;
[XmlRoot("ChartXml")]
public class ChartXml
{
[XmlElement("Category")]
public Category Category;
}
public class Category
{
[XmlAttribute("type")]
public string Type;
[XmlArray("Value")]
public List<string> Values;
}
Now when I try to serialise the XML to a ChartXml object, I get object containing the Category with the type attribute set correctly, but i dont get my list of strings.
I'm guessing its something wrong with the way i've set up my classes.
Thanks,
james.
Use [XmlElement("Value")] instead of [XmlArray("Value")], e.g.:
[XmlRoot("ChartXml")]
public class ChartXml
{
[XmlElement("Category")]
public Category Category;
}
public class Category
{
[XmlAttribute("type")]
public string Type;
[XmlElement("Value")]
public List<string> Values;
}
Serialization:
var obj = new ChartXml { Category = new Category { Type = "t", Values = new List<string> { "a", "b", "c" } } };
var ser = new XmlSerializer(obj.GetType());
using (var tw=new StringWriter())
{
ser.Serialize(tw, obj);
Console.WriteLine(tw.ToString());
}
Output:
<?xml version="1.0" encoding="utf-16"?>
<ChartXml xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http:
//www.w3.org/2001/XMLSchema">
<Category type="t">
<Value>a</Value>
<Value>b</Value>
<Value>c</Value>
</Category>
</ChartXml>
Use [XmlElement("Value")] instead of [XmlArray("Value")]
How to convert XML Elements to of type Person ?
Elements :
XElement persons = XElement.Parse(
#"<persons>
<person>
<id>10001</id>
<name> Daniel </name>
</person>
<person>
<id>10002</id>
<name>Marshal</name>
</person>
<person>
<id>10003</id>
<name>Leo</name>
</person>
</persons>"
);
Person Type:
class Person
{
int personID;
string name;
public int PersonID
{
get {return personID;}
set {personID = value;}
}
public string Name
{
get {return name;}
set {name = value;}
}
}
I tried (incomplete & not sure whether valid approach )
Person[] Prns = from perns in persons.Nodes select new {perns};
var personList =
from p in persons.Elements("person")
select new Person
{
Name = p.Element("name").Value,
PersonID = int.Parse(p.Element("id").Value)
};
Another option would be to use XML serialization, but using LINQ to XML is probably easier:
[XmlType("person")]
public class Person
{
int personID;
string name;
[XmlElement("id")]
public int PersonID
{
get { return personID; }
set { personID = value; }
}
[XmlElement("name")]
public string Name
{
get { return name; }
set { name = value; }
}
}
…
var serializer = new XmlSerializer(typeof(Person[]), new XmlRootAttribute("persons"));
var result = (Person[])serializer.Deserialize(new StringReader(xml));