Serialize only a part of xml file and save it - c#

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.

Related

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.

Deserialization with options

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());
}

Nesting XML and using DataSets etc

I have a nested XML document and I am looking at the plausability of using DataSets to parse it.
<?xml version="1.0" standalone="yes"?>
<Workbench>
<Overrides>
<Override name='firstoverride' value='overridevalue'/>
</Overrides>
<DataSets>
<BASIC>
<MEMBNO>1</MEMBNO>
<PERSONNO>0</PERSONNO>
</BASIC>
</DataSets>
</Workbench>
What i want to be able to do is essentially access the contents of the Overrides and DataSets as if there were an actual Dataset.
So to validate I check the root element is workbench.
Then I check to see if there are any overrides, I then want to be able to iterate around the Override Items.
Following that, and this is the hard part I want to support abitary but well form XML that will be inserted into a database but the parsing code can make so assumptions about the data as I want it to be generic.
I can do this if I make the DataSets the root element and iterate around it but it doesn't seem to work if nested?
hlep!

Class Design related clarification c#

I have a design related question. So please guide me on how to do this?
Right now, I have a xml structure which will be in this format.
<Sheet id="abc"/>
<Elements>
<Element id="xyz">
<value>23</value>
</Element>
<Element id="sdz">
<value>46</value>
</Element>
...
</Elements>
</Sheet>
So, we have a class like this to store each & every element of the sheet.
Sheet
{
Public string SheetId
{
get; set;
}
//all Elements will be stored in the below collection
Public IList<IDictionary<string, string>> Elements
{
get; set;
}
}
But now for few sheets the format has been changed to the below structure.
<abc> //SheetId
<Elements>
<Record>
<Element1/>
<Element2/>
<Element3/>
<Element4/>
</Record>
<Record>
<Element1/>
<Element2/>
<Element3/>
<Element4/>
</Record>
...
</abc>
So, we need to create a Generic class to hold the above xml formats and we don't want to have different object to store these.
I mean in future if we have some other xml format also we need to accommodate the same without any change in the Sheet class.
So, can you please advise me on how to design the Sheet Class.?
Ok. let me explain how my app works.
Actually we have around 200 sheets(in other words measures).
1) User will upload the sheet data in xml format (all sheets in xml file) & edit the same if they want Or Enter the data in the screen (dynamic screen generated using the xml template) if they dont want to upload.
2) Then the data will be stored in the Sheet object and it will go through lot of Validation process and finally the data will be converted to xml again and stored in the db.
You can ask why you want to store this as XML? The reason is we dont want to create 200 aspx pages for this same kind of data and thats why we are generating the sheet pages dynamically using the xml templates. Also, we will be adding, updating or deleting sheets frequently.
Ok. I think now you will have some idea about this issue.
To be more clear, all the elements in my XML file will be displayed as a field in the aspx page. It maybe a Textbox, dropdown & etc....
I would recommend designing your class based on what the information actually represents and how your software plans to utilize the data, not the XML format being used.
You should always be able to do the transposition from the data format into the structure which best represents how your program will use this data.

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