Write to existing xml file without replacing it's contents (XmlWriter) - c#

I encountered following issue,
I first write to my xml file like this:
XmlTextWriter writer = new XmlTextWriter("course.xml", null);
writer.Formatting = Formatting.Indented;
writer.WriteStartDocument();
writer.WriteStartElement("Course");
writer.WriteAttributeString("title", "Examle");
writer.WriteAttributeString("started", "true");
writer.WriteEndElement();
writer.WriteEndDocument();
writer.Close();
And xml output I get is:
<?xml version="1.0"?>
<Course title="Example" started="true" />
After that I want to write more data to this xml file so I use my code again:
XmlTextWriter writer = new XmlTextWriter("course.xml", null);
writer.Formatting = Formatting.Indented;
writer.WriteStartDocument();
writer.WriteStartElement("Course");
writer.StartElement("Level");
writer.StartElement("Module");
writer.EndElement();
writer.EndElement();
writer.WriteEndElement();
writer.WriteEndDocument();
writer.Close();
And the xml output is:
<?xml version="1.0"?>
<Course>
<Level>
<Module>
</Module>
</Level>
</Course>
So it replaces my original data, and all attributes in the course tag. Therefore I need a way where it doesn't replace data, but instead add it inside existing tags.

XML files are just sequential text files. They are not a database or a random-access file. There is no way to just write into the middle of them.

I would recommend parsing the entire xml document into memory, adding the new data, and then writing the whole document back out again.

Related

How do I add a CDATA to an already existing ElementString? (C#)

I have my XML file setup like this:
<Entry>
<Desired_due_date>date</Desired_due_date>
<Order_number>order</Order_number>
<Series_number>series</Series_number>
<Product_name>product</Product_name>
</Entry>
I want to add CDATA without dropping the tags f.e.:
<Product_name>[CDATA[Z19 7HW]]</Product_name>
Every solution I found either makes a new node which messes up my structure or drops the tags.
My code looks something like this:
writer.WriteComment("Results in XML format.");
writer.WriteStartElement("Entries");
writer.WriteElementString("Series_number", entries[i].Series_number);
writer.WriteElementString("End_date_2", entries[i].End_date2);
writer.WriteElementString("Norm", entries[i].Norm);
writer.WriteEndElement();
writer.WriteEndDocument();
writer.Flush();
writer.Close();
Do not use XmlWriter.WriteElementString. Instead:
writer.WriteStartElement("elementname");
writer.WriteCData("text that goes in CDATA section");
writer.WriteEndElement();

Find and append to file without loading it in memory?

Im writing a simple XML file for logging that looks like this :
<root>
<objects>
</objects>
</root>
The file is created the first time like this
using (xmlWriter = new XmlTextWriter(filePathAndName, System.Text.Encoding.UTF8))
{
xmlWriter.Formatting = Formatting.Indented;
xmlWriter.WriteStartDocument();
xmlWriter.WriteStartElement("root");
xmlWriter.WriteStartElement("objects");
xmlWriter.WriteEndElement();
xmlWriter.WriteEndElement();
xmlWriter.WriteEndDocument();
xmlWriter.Close();
}
Now I need to place objects(serialized data contracts in string format) within the objects tag without loading it to memory.
I have found a lot of suggestions on how to do this but all loads the entire file into memory and thats no good when the files is large.
My thought is this :
Open file with some kind of reader
Search from end of file to </objects> tag
Store the index and close the reader/file
Open the file again but this time as a writer
Write the serlized datacontract to the index(just before the
Close file
I'm however not sure how to do this properly in C#?
The solution for me in this case was XML Inclusion Technique, it is not perfect but the login is much simplier. I can use appendToFile instead of manipulate or read into memory.

Windows Form project proper format for XML in TextBox field

on my project i have a form in which i have TextBox in some point of executing my program i want to put XML string in my TextBox - nothing complicated. Problem lies in the format in which this XML is being displayed in TextBox which is:
<?xml version="1.0" encoding="utf-16" ?><IOTPMessage xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Element1>value</Element1><Element2>value</Element2><Element3>value</Element3></IOTPMessage>
I want it to look like proper XML look like (with new lines, tabulators) which is easy to read :
<?xml version="1.0" encoding="utf-16" ?>
<IOTPMessage xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Element1>value</Element1>
<Element2>value</Element2>
<Element3>value</Element3>
</IOTPMessage>
The way i put XML string to textBox:
TextBox someBox;
someBox.Append(XMLstring);
To be honest i don't even knew where to start - besides looking for proper articles or samples which i didn't find, maybe anyone of you can redirect me to somewhere where i can find solution?
You may use XmlTextWriter in order to show proper XML Message like here:
MemoryStream w = new MemoryStream();
XmlTextWriter writer = new XmlTextWriter(w, Encoding.Unicode);
XmlDocument document = new XmlDocument();
document.LoadXml(xmlString);
writer.Formatting = Formatting.Indented;
document.WriteContentTo(writer);
writer.Flush();
w.Seek(0L, SeekOrigin.Begin);
StreamReader reader = new StreamReader(w);
return reader.ReadToEnd();

how to use XMLTextWriter to write XML node at a specified position

I have an xml file likes below.
<?xml version="1.0" encoding="utf-8" ?>
<Book>
<Title>Title</Title>
<Content>Content</Content>
</Book>
I want to write a new node after 'Content', I know how to use XMLDocument to do that, is there a way to use XMLTextWriter to do that?
You will have to write the whole Xml document, i.e. all elements and attributes and attribute values by using the XmlTextWriter. After you've written the <Content> element, you can write your additional element.
Something like this:
writer.WriteStartDocument();
writer.WriteStartElement("Book");
writer.WriteStartElement("Title");
writer.WriteString("Title");
writer.WriteEndElement();
writer.WriteStartElement("Content");
writer.WriteString("Content");
writer.WriteEndElement();
// insert your new data here
writer.WriteEndElement();
writer.WriteEndDocument();

how Deserializing this type of xml file?

<row>
<id>1</id>
<code></code>
<name></name>
<address></address>
<state></state>
<zone>?</zone>
</row>
<row>
<id>2</id>
<code>AA</code>
<name>Ataria</name>
<address>Sitapur National Highway 24, Uttar Pradesh</address>
<state>Uttar Pradesh</state>
<zone>NER</zone>
</row>
i have no root element in this xml file only row element start and end this xml file.
how Deserializing this type of data ? in c#
If you sure that missing root is only the one issue with your XML - just add it manually:
string fileContent = File.ReadAllText(path);
string rawXml = "<root>" + fileContent + "</root>";
// now you can use LINQ-to-XML or whatever
XDocument xdoc = XDocument.Load(rawXml);
You can also load an XML Fragment directly, via
XmlReaderSettings settings = new XmlReaderSettings();
settings.ConformanceLevel = ConformanceLevel.Fragment;
using (XmlReader reader = XmlReader.Create("tracelog.xml", settings))
{
while (reader.Read())
{
// Process each node of the fragment,
// possibly using reader.ReadSubtree()
}
}
You would create XElements by passing the results of reader.ReadSubTree() to XElement.Load(...).
Well to start with, it's not an XML file - or at least, it doesn't represent an XML document.
One option would be to copy the file into a new file which does have document start/end tags... then you can load it as a normal document. Just create a file, write a document start tag, copy the contents of this file, then write a document end tag, and close the file handle. You could even do this in memory.
Alternatively, it may be possible to read it as it is, in fragments - possibly via XmlReader. I can't say it's something I've done, and I'd generally encourage you to create a full XML file instead, as then you'll be on more familiar territory.
its not an XML file if it doesn't have the root. parser will throw an error if you try to parse it. you can do this way
<?xml version="1.0"?>
<Root>
--- add your file content here
</Root>
then give this file path to the parser.

Categories