modifying pseudo-xml doc before it hits XmlDocument.Load - c#

I have a series of... pseudo-xml files. What I mean by this, is they are almost XML files, but they are missing the xml declaration and a root node. e.g. conceptually it may look like this:
<a>info</a>
<b>info2</b>
What I want to do is load it into an XmlDocument object, e.g something similar to this:
XmlDocument xml = new XmlDocument();
using (StreamReader file = new StreamReader(File.Open(#"file.txt", FileMode.Open, FileAccess.Read, FileShare.ReadWrite)))
{
xml.Load(file);
}
This is throwing errors, most likely due to the ill formatted pseudo-xml file. I need to somehow handle adding in a root node before it hits the Load. I don't want to modify the actual file, or have to save anything to disk (e.g. a new temp file). I'm stuck on this, any suggestions?

XmlDocument has also a LoadXml() method that parses an Xml string. You can load your file content into a string, add the declaration and call LoadXml().
Of course, when you are using long files, this can be very memory consuming, pay attention to that.

you could try this
var xmlString = file.ReadToEnd();
xmlString = "<root>" + xmlString + "</root>";
xml.LoadXml(xmlString);

Related

Serialize to an XML document without overwriting previous data

I need to serialize to an XML document without overwriting the data that is currently in there. I have a method that does this and it will save to the xml file, but will delete whatever is currently in that file upon serializing. Below is the code.
public void SaveSubpart()
{
SOSDocument doc = new SOSDocument();
doc.ID = 1;
doc.Subpart = txtSubpart.Text;
doc.Title = txtTitle.Text;
doc.Applicability = txtApplicability.Text;
doc.Training = txtTraining.Text;
doc.URL = txtUrl.Text;
StreamWriter writer = new StreamWriter(Server.MapPath("~/App_Data/Contents.xml"));
System.Xml.Serialization.XmlSerializer serializer;
try
{
serializer = new System.Xml.Serialization.XmlSerializer(doc.GetType());
serializer.Serialize(writer, doc);
}
catch (Exception ex)
{
//e-mail admin - serialization failed
}
finally
{ writer.Close(); }
}
The contract for the StreamWriter constructor taking only a filename says that if the named file exists, it is overwritten. So this has nothing to do with serializing to XML, per se. You would get the same result if you wrote to the stream through some other means.
The way to do what you are looking for is to read the old XML file into memory, make whatever changes are necessary, and then serialize and write the result to disk.
And even if it was possible to transparently modify an on-disk XML file, that's almost certainly what would happen under the hood because it's the only way to really do it. Yes, you probably could fiddle around with seeking and writing directly on disk, but what if something caused the file to change on disk while you were doing that? If you do the read/modify/write sequence, then you lose out on the changes that were made after you read the file into memory; but if you modify the file directly on disk by seeking and writing, you would be almost guaranteed to end up with the file in an inconsistent state.
And of course, you could only do it if you could fit whatever changes you wanted to make into the bytes that were already on disk...
If concurrency is a problem, either use file locking or use a proper database with transactional support.
try this:
StreamWriter writer = new StreamWriter(Server.MapPath("~/App_Data/Contents.xml"),true);
this determines to append the data to the file.
true=append,
false = overwrite
more info http://msdn.microsoft.com/en-us/library/36b035cb.aspx
So what you want to implement is to serialize an object without overwriting it to an existing file.
Thus
XmlSerializer s = new XmlSerializer(doc.GetType());
TextWriter w = new StringWriter();
s.Serialize(w, doc);
var yourXMLstring = w.ToString();
Then you can process this xml string and append it to existing xml file if you want to.
XmlDocument xml = new XmlDocument();
xml.LoadXml(yourXMLstring );

Is it possible to reload an XDocument and keep all existing references to it?

I've got an XDocument created via XDocument's static Load method (taking an XmlReader) as follows:
XDocument doc;
doc = XDocument.Load(reader);
Now, it's necessary at some point to reload the document (restoring to the original version after changes have been made). The obvious way to do this seems to be doc = XDocument.Load(reader);. However, this will create a new XDocument, and any existing references to doc will still point at the old (altered) version despite the fact that we've (re)loaded the original.
Is there a way to load an XmlReader (or even a string or byte[] representation of XML) into an existing XDocument, overwriting the contents? Or would I have to make all of the changes (dropping its elements and adding new ones) manually?
You should be able to do
doc.Root.ReplaceWith( XElement.Load(fileName));
If you want to preserve processing instructions you may need to Load into a temp XDocument first.
You can replace the root of the XDocument.
var oldDoc = new XDocument();
oldDoc.Add(new XElement("OldRoot"));
var newDoc = new XDocument();
newDoc.Add(new XElement("NewRoot"));
oldDoc.Root.ReplaceWith(newDoc.Root);

load xml file into memory

I need to load a xml file in memory so I can access it several times from different forms.
The xml is in this format:
<Slides>
<Slide>
<Name>Name 1</Name>
<Value>Value 1</Value>
<Type>Type 1</Type>
</Slide>
<Slide>
<Name>Name 2</Name>
<Value>Value 2</Value>
<Type>Type 2</Type>
</Slide>
</Slides>
I don't want to use a database to store the vars. Is there any other method to store the data in memory?
Right now I'm using a txt file for each slide and streamreader, which I'm sure is not the best option.
EDIT:
I added this code, but will I be able to get the slides every time without reading the xml file again?
var slides = from s in XElement.Load("slides.xml").Elements("Slide")
select s;
foreach (var slide in slides)
{
//code
}
You should use the XDocument Load method: http://msdn.microsoft.com/en-us/library/bb343181.aspx
i think it is better to use XDocument than the XmlDocument... but it depends on your requirements...
The XDocument is more memory optimized than the XmlDocument, and i think they both are easy for use (for getting values from the xml)
See the XmlDocument class. The Load() method does what you want.
First you have to save the xml file in your project file or your hard disk.Then only you can load the xml file in code behind.
You can create xml file dynamically.it will be much better.
using System.Xml;
XmlDocument myxml = new XmlDocument();
myxml.Load("D:/sample.xml");//Load you xml file from you disk what you want to load
string element_1 = myxml.GetElementsByTagName("Name")[0].InnerText;
string element_2 = myxml.GetElementsByTagName("Value")[0].InnerText;
string element_3 = myxml.GetElementsByTagName("Value")[0].InnerText;
string element_4 = myxml.GetElementsByTagName("Name")[1].InnerText;
string element_5 = myxml.GetElementsByTagName("Value")[1].InnerText;
string element_6 = myxml.GetElementsByTagName("Value")[1].InnerText;
Try this program it will help you.

XDocument File Name

Is there a way to retrieve XDocument saved path (file name) from the XDocument object itself?
I mean to get the saved path after I already saved the XDocument object. Something like this:
XDocument xDoc = new XDocument();
xDoc.Save(#"C:\Temp\MyXmlDoc.xml");
string str = xDoc.SavedPath() // <== something like this
If you load the XDocument from a file, the BaseUri property will contain the file name. As stated in MSDN:
Sometimes the XmlReader has the base
URI, and sometimes it does not. For
instance, when loading from a file,
the XmlReader knows the base URI, but
when reading from an XmlReader that
was created because of calling the
Parse method, there is no possibility
of the XmlReader reporting a base URI;
the XML was in a string.
However, this is not set when saving the document, only during load operations. Therefore, if you need to know the save path, you will need to store that independently of the XDocument instance when saving.
No, an XDocument does not remember where it has been saved to.
You have to remember the path yourself, e.g.
XDocument xDoc = new XDocument();
string str = #"C:\Temp\MyXmlDoc.xml";
xDoc.Save(str);

How to Verify using C# if a XML file is broken

Is there anything built in to determine if an XML file is valid. One way would be to read the entire content and verify if the string represents valid XML content. Even then, how to determine if string contains valid XML data.
Create an XmlReader around a StringReader with the XML and read through the reader:
using (var reader = XmlReader.Create(something))
while(reader.Read())
;
If you don't get any exceptions, the XML is well-formed.
Unlike XDocument or XmlDocument, this will not hold an entire DOM tree in memory, so it will run quickly even on extremely large XML files.
You can try to load the XML into XML document and catch the exception.
Here is the sample code:
var doc = new XmlDocument();
try {
doc.LoadXml(content);
} catch (XmlException e) {
// put code here that should be executed when the XML is not valid.
}
Hope it helps.
Have a look at this question:
How to check for valid xml in string input before calling .LoadXml()

Categories

Resources