Deserialization with options - c#

I am currently achieving serialization of a collection to the file. The results are like how I expect
<Persons>
<Person>
<Identity>1234</Identity>
<Name>asd</Name>
</Person>
<Person>
<Identity>12345</Identity>
<Name>asdd</Name>
</Person>
</Persons>
Now, I don't want to deserialize the whole collection but I want to deserialize an object from the file with some specific options. For example,
object GetPersonWithIdentity(int identity )
{
// what to do here
}
object asd = GetPersonWithIdentity(1234);
// expected Person with Identity "1234" and Name "asd"
Is it be reasonable to deserialize whole collection and find the specific object and return it, or is there any other solution for this?

XML is not seekable so you at least have to read forward till you find the first match. The framework does not support that automatically so you have to do it manually using an XmlReader which is laborious.
If the file is small and/or performance is not an issue, just deserialize everything and be done with it.
If your dataset is big I'd consider moving to some more scalable format like an embedded SQL database. SQL databases have this capability inherently.

You will have to serialize the entire XML file because as usr mentioned, XML is forward only. XmlReader/Writer is essentially a TextReader (Stream) object, and is doing file i/o to read an XML file.
The reason for my seperate answer is I would do the following using an XDocument object:
object GetPersonWithIdentity(int identity )
{
return myXDocumentVaraible.Descendants("Person")
.First(person => person.Element("Identity").Value == identity.ToString());
}

Related

Accessing XML elements using C#

I'm having the program shown below:
When the user selects a Client, and after specifying the date using the datePicker, the date should be added under the water request for the same user.
We might have more than one request for each client.
The structure of my XML file is as follows:
<clients>
<record>
<Name></Name>
<Surname></Surname>
<Mobile></Mobile>
<Address></Address>
<Request>
<date></date>
</Request>
</record>
</clients>
Can you help me with this one please?
I've walked through this example:
string xtitle = textBox1.Text.ToString();
XDocument xmlDoc = XDocument.Load("Book.xml");
XElement element =
xmlDoc.Root.Elements("book").Where(r => (string)r.Element("Isbn") == xtitle).FirstOrDefault();
if (element != null)
{
element.SetElementValue("Isbn", textBox1.Text);
element.SetElementValue("Book_Name", textBox2.Text);
element.SetElementValue("Price", textBox3.Text);
element.SetElementValue("Date_of_Publication", textBox4.Text);
element.SetElementValue("Number_of", textBox6.Text);
element.SetElementValue("Category", textBox7.Text);
}
xmlDoc.Save("Book.xml");
Supposing that "ISBN" has another subelement, how can I access it?
XDocument xmlDoc = XDocument.Load("Book.xml");
You can use Linq to Xml to get the Request element and add the date node to it.
var requestDate = DateTime.Today; //Get the date from the date picker
var requestElement = xEle.Descendants("Request").FirstOrDefault();
if(requestElement != null)
{
requestElement.Add(new XElement("date", requestDate));
xmlDoc.Save("Book.xml");
}
I think I would prefer to define the corresponding classes and objects and use an XML serializer constructed from them to read and save the file.
You would need to learn how to use the serializable interface. Look here. Using that, you will create classes to hold the data objects that you would read from the xml file. The structure of the classes will match the structure of your xml file, so that you will have a request class that just has a date property. You will also have a "Client" class that has a collection of request objects as one of its properties, along with client name, etc.
Using the outermost class, you will construct an xml serializer which you can then use to deserialize (read from text/xml file into actual objects in memory) and serialize the file (save from the objects in memory back to a text/xml file. This is just a couple of lines of code that you will find here.
In memory, you will have an array or a collection of Client objects. You can then use LINQ to mess with that collection - insert, sort, delete. You can bind your listbox to that collection to display its data.
Hope this helps.

Fastest Way of reading XML

I have an XML file in which I store data about a list of persons and another one in which I store a list of objects like this.
people.xml
<People>
<Person>
<Name>itsName</Name>
<Age> itsAge </Age>
<RecentAcquisitions>
<Acquisition>
<name>Apple</name>
<quantity>5</quantity>
</Acquisition>
</RecentAcquisitions>
</Person>
</People>
objects.xml
<Objects>
<Object>
<Name>Apple</Name>
<Description>Fresh Apple</Description>
<Price>10</Price>
<etc>..lots of attributes..</etc>
</Object>
</Objects>
What is the most efficient way of extracting information from objects.xml based on the person Acquisition List at the runtime? (in example the person should have 5 objects of type "Apple").
Momentarily I use a solution which consists of storing each object from objects.xml in a list and when I'm loading a person I search for the respective object based on Acquisition->Name and add it in the person.AquisitionList;
Is there another way of doing this?
Maybe I misunderstood the XML role but it feels wrong to store the information from an XML file in a list or array at runtime.
to my knowledge, using the runtime memory instead of constant read-write operations is the best way to do it / what you're doing is the right way.
XML can be seen as 2 things:
1 - A way to store information, much like a database, until it needs to be retrieved for processing at runtime
this is what you are doing now... you store the objects list on disk using XML, and then you retrieve it for processing/load it into memory at runtime.
2 - A standardized way of passing information around, regardless of technology.
XML can be read in a multitude of languages and any language that can read a string can technically read and extract the data from an XML document.

Serialize only a part of xml file and save it

I have a problem with respect to XML Serialization. I shall try to explain it with the following example xml file
<AutoExpo>
<Details>
<Venue>XYZ</Venue>
<StartTime>09:00</StartTime>
<EndTime>21:00</EndTime>
</Details>
<Cars>
<Car>
<Company>Chevrolet</Company>
<Model>Cruz</Model>
<Color>Red</Color>
</Car>
<Car>
<Company>Ford</Company>
<Model>Fiesta</Model>
<Color>Blue</Color>
</Car>
</Cars>
</AutoExpo>
Now, when I read this xml file, I deserialize the cars into objects. The car list can be huge. My code uses this objects and can change the properties of some cars. Now what if I want to serialize only those car objects whose properties have changed, back to the xml file and save it so that next time when my code starts it gets the latest state information.
It would be quite difficult to jump around in the XML file changing properties here and there, wherever they have changed. You should just read the whole file into memory, and when you save, write out the whole thing, overwriting the old file.
XML isn't a terrible way of doing this, but as far as I can tell from the question, a SQL Server (or other RDBMS) database would be much more appropriate. You won't have to worry about issues like this, as the DB engine will do that for you.
Although it may not be the best solution, a potentially viable option would be to serialize the edited list to a seperate file and, in code, compare the two files. If there hasn't been any changes to the information the two text files should be identical. If not, you can replace the old file with the new file. The easiest way would be, rather than serialize to a file and read/write it, perhaps send it to a stream and compare them.
When you serialize an object, it generates the entire XML document. So, if you save that to a file, it will overwrite the previous content of the file. Therefore, if you want the resulting file to contain all the cars, including, but not limited to, the modified ones, then you need to serialize the whole thing. If you only serialized the ones that changed, the file would lose all the cars that did not change. If you really do only want to serialize the changed cars, I would suggest creating a new instance of the AutoExpo object and only insert into it the cars that you want to save, then serialize that object with only the partial list.
If you need to just modify a single element in the XML without touching the rest of it because the data is too big, XML is not a good choice. I would suggest a relational database instead. Alternatively, you could store each car as its own XML file and only load and save each one individually as necessary.
You cannot do that with XML. Consider using a relational database. Relational databases have a built-in file space management mechanism allowing doing exactly what you need. You can update single records, add and delete records.
A Jet .mdb database (Access) is a good candidate for the replacement of a XML-File. You can access it via OLEDB with the restriction that the application must be compiled for 32 bit. Access needs not to be installed.
First of all, your entities must have unique identifiers.
<AutoExpo>
<Details>
<Venue>XYZ</Venue>
<StartTime>09:00</StartTime>
<EndTime>21:00</EndTime>
</Details>
<Cars>
<Car id="1">
<Company>Chevrolet</Company>
<Model>Cruz</Model>
<Color>Red</Color>
</Car>
<Car id="2">
<Company>Ford</Company>
<Model>Fiesta</Model>
<Color>Blue</Color>
</Car>
</Cars>
</AutoExpo>
Now you could use XPath to select those nodes that require updates and change their content.
load the document into an XDocument
find a car: document.Element("Car[id=2]")
set the new value: element.Element("Color").Value = "Black"
However, the downside of using a file-based storage remains. You still have to load the whole file into memory and write it back to the hard drive when you're down updating, but you do not have to serialize all Car objects.
I can't think of an easy way to stream the file from hard drive and manipulate it in one go.

How do I use LINQ to parse XML with child elements of the same name?

Background Information:
In the past, I have been picking up a collection of XML files and iterating through each XML file, parsing it, passing string data to a data transfer object and passing the object into a database.
Before, my XML looked like this.
<messages>
<message>
<title>Red Wall</title>
<summary>This is a good article</summary>
<ISBN>13546846545464</ISBN>
</message>
</messages>
Here, I only have one element. So, I would parse the XML by using LINQ and retrieve the subsequent elements(title, summary, isbn). Then I would initialize/instantiate an object, assign its properties to the values I retrieved, and send it along.
Now my XML looks like this:
<messages>
<message>
<title>Red Wall</title>
<summary>This is a good article</summary>
<ISBN>13546846545464</ISBN>
</message>
<message>
<title>Blue Wall</title>
<summary>This is not a good article</summary>
<ISBN>15648465416</ISBN>
</message>
</messages>
I now have two (or more) elements in my XML file, and for each one I need to 1) identify that there are multiple elements and 2) for each create a separate DTO to hold the data that I parse.
My question is: How do I parse XML with multiple tags and identify each one I encounter as being separate from the other?
Final Note: While parsing, I need to be able to instantiate a DTO to capture the information I get returned back.
Thanks for helping!
Just Grab the element you want and use your select to populate the dto from the child items. Something like this not tested
XElement ele = loaded.Element("messages");
dtos = from item in ele.Descendants("message")
select new DTO() {title = item.Element(title).value ,... };
The select statement above is going to return an IEnumerable<DTO>, which is a sequence of DTO objects. For every message node it finds in the XML, it will create a DTO object and add it to the sequence returned. If your goal is just to iterate over all the DTOs, you're already there. If you actually need a List<DTO>, there is a constructor on the generic List object that takes an IEnumerable<T>, so you could pass in the "dtos" you received from the select statement and have a List.

Reading and using an XML file as a database - Windows Phone 7 app

I have an app which should read the data from an xml file and then use that data.
How can I import an xml file in my app (what's the code for that) and how can I use the data from that xml file?
Here's an example of the xml database I use:
<Data>
<Animals>
<A>
<word>Ant</word>
<word>Aardwark</word>
</A>
<B>
<word>Bear</word>
<word>Boa</word>
</B>
</Animals>
</Data>
Also I tried this
XDocument loadedData = XDocument.Load("Data.xml");
to read the data from the xml file but didn't work.
Also the in what form can I use the xml data? In other words the xml data would be in a string format or an "X-Something" format?
Update: Maybe Xml Deserialization would work for me?
Thank you in advance
If "Data.xml" is in the root of the project, make sure the Build Action is set to Content and your code should work.
Linq2XML is your friend, and will help you do just that! Mind you that it'll be read-only, unless you place it in the Isolated Storage.
No need for IsoStore if you already have the file and it is the same for every app instance (given that you only need to read it). Simply do what Matt said to quickly get the contents. I would recommend deserializing it to a separate class, so that you can easily reuse and modify the data.
Now, if you want to store the data, you can later easily serialize the existing class and store it locally. In case you want to go a bit deeper into data storage, you could use SQL CE, that is included in Mango and will allow you to manipulate SDF files (which, by the way, can be loaded separately with app instances). Also, a good idea would be to look into Sterling DB (will use IsoStore).
Using the System.XML namespace, use the following code.
XmlDocument xml = new XmlDocument();
xml.LoadXml("your string of xml");
XmlNode xNode = xml.SelectSingleNode("xpath to a single node");
XmlNodeList xNodeList = xml.SelectNodes("xpath to multiple nodes");
You can treat xNode and xNodeList kind of like array results sets and view their contents using the bracket syntax like xNodeList[0].

Categories

Resources