Append to an XML File using XMLWriter class in C# - c#

I have a method which creates an xml file and this method is frequently called from other classes. I have sent three parameters to this method and while writing the xml file I need to append in the xml file with those three parameters. Here's my code snippet
XmlWriterSettings settings = new XmlWriterSettings();
settings.Indent = true;
XmlWriter writer = XmlWriter.Create(#"E:\\log.xml", settings);
writer.WriteStartDocument();
writer.WriteStartElement("Log");
writer.WriteStartElement("Tests");
writer.WriteStartElement("Test");
writer.WriteAttributeString("Test", message);
writer.WriteElementString("DateAndTime", time);
writer.WriteElementString("Result", test);
writer.WriteEndElement();
writer.WriteEndElement();
writer.WriteEndElement();
writer.WriteEndDocument();
writer.Flush();
writer.Close();
I get his output :
<?xml version="1.0" encoding="utf-8"?>
<Log>
<Tests>
<Test Test="LoginToAcrm">
<DateAndTime>2014-20-28 06:20:40</DateAndTime>
<Result>Passed</Result>
</Test>
</Tests>
</Log>
Can anyone please tell me what should I change in my code so that when I call the method again with these three parameters it will append to this xml file with the same format, not overwrite the previous file. Something will be like this:
<?xml version="1.0" encoding="utf-8"?>
<Log>
<Tests>
<Test Test="LoginToAcrm">
<DateAndTime>2014-20-28 06:20:40</DateAndTime>
<Result>Passed</Result>
</Test>
</Tests>
<Tests>
<Test Test="LoginToProjectWithError">
<DateAndTime>2014-09-28 05:10:45</DateAndTime>
<Result>Failed</Result>
</Test>
</Tests>
<Tests>
<Test Test="LoginToProjectWithBlank">
<DateAndTime>2014-09-28 05:12:13</DateAndTime>
<Result>Passed</Result>
</Test>
</Tests>
</Log>

I used some your code, use StringBuilder to create XmlWriter and finally write that string using StreamWriter.
XmlWriterSettings settings = new XmlWriterSettings();
settings.Indent = true;
settings.OmitXmlDeclaration = true;
StringBuilder sb = new StringBuilder();
XmlWriter writer = XmlWriter.Create(sb, settings);
writer.WriteStartDocument();
writer.WriteStartElement("Tests");
writer.WriteStartElement("Test");
writer.WriteAttributeString("Test", message);
writer.WriteElementString("DateAndTime", time);
writer.WriteElementString("Result", test);
writer.WriteEndElement();
writer.WriteEndElement();
writer.WriteEndDocument();
writer.Flush();
writer.Close();
using (System.IO.StreamWriter file = new System.IO.StreamWriter(#"E:\\log.xml", true))
{
file.Write(sb.ToString());
}

You can achieve this by passing List of strings as arguments to the function. And for your help i did the coding of the complete function. Let me know if this work out for you. Check this out
void xmlwriter(List<string> message, List<string> time, List<string> test)
{
XmlWriterSettings settings = new XmlWriterSettings();
settings.Indent = true;
XmlWriter writer = XmlWriter.Create(#"E:\\log.xml", settings);
writer.WriteStartDocument();
writer.WriteStartElement("Tests");
string[] arrayMessage = message.ToArray();
string[] arrayTime = time.ToArray();
string[] arrayTest = test.ToArray();
for (int i = 0; i < arrayMessage.Length; i++)
{
writer.WriteStartElement("Test");
writer.WriteAttributeString("Test", arrayMessage[i]);
writer.WriteElementString("DateAndTime", arrayTime[i]);
writer.WriteElementString("Result", arrayTest[i]);
writer.WriteEndElement();
}
writer.WriteEndElement();
writer.WriteEndDocument();
writer.Flush();
writer.Close();
}
Note: You may have to add all the values of the parameters to the List before you call the function.

Your desired result isn't a well-formed XML document, since an XML document may only have a single root element.
However, if this is what you want (i.e. rather than an XML document, you want a text document containing XML fragments), you could try the following:
Open the existing file as a FileStream
Seek to the end of file
Pass the FileStream to your XmlWriter constructor
Append the elements you want

Related

Create start XML manually

I want to create XML file so i am using this way:
XmlWriterSettings settings = new XmlWriterSettings
{
Indent = true,
Encoding = Encoding.Unicode
};
string xmlPath = #"c:\file.xml";
XmlWriter xmlWriter = XmlWriter.Create(xmlPath, settings);
xmlWriter.WriteStartDocument(false);
Result:
<?xml version="1.0" encoding="utf-16" standalone="no"?>
<cp>
<user>NA</user>
<password>NA</password>
</cu>
But i want this start XML will be Upper case:
<?xml version="1.0" encoding="UTF-16" standalone="no"?>
So i try to create this start manually:
XmlWriterSettings settings = new XmlWriterSettings
{
Indent = true,
Encoding = Encoding.Unicode
};
string xmlPath = #"c:\file.xml";
XmlWriter xmlWriter = XmlWriter.Create(xmlPath, settings);
xmlWriter.WriteRaw("<?xml version=\"1.0\" encoding=\"UTF-16\" standalone=\"no\"?>\r\n");
But the result was that i received the start twice:
<?xml version="1.0" encoding="utf-16"?><?xml version="1.0" encoding="UTF-16" standalone="no"?>
You can add the following line before you start writing the xml.
That is,
settings.OmitXmlDeclaration = true;
string xmlPath = #"c:\file.xml";
XmlWriter xmlWriter = XmlWriter.Create(xmlPath, settings);
xmlWriter.WriteRaw("<?xml version=\"1.0\" encoding=\"UTF-16\" standalone=\"no\"?>\r\n");
This way your xml will be created not with the default declaration, but with the one that you are adding exclusively.

C# XML Serilization & Appending new data

I am trying to create an XML file with the following structure
However, this is what I get (one line):
<?xml version="1.0" encoding="utf-8"?><!--This file is generated by the program.--><root><OFBM time="9:15" date="22.06.2016"><folder>file:///C:/Program Files (x86)/Cisco/Cisco AnyConnect Secure Mobility Client</folder><folder>file:///C:/Arduino223</folder></OFBM></root>
My code:
public void CreateXML()
{
XmlWriter writer = XmlWriter.Create(#"C:\Users\Alek\Dropbox\D\Debug\product.xml");
writer.WriteStartDocument();
writer.WriteComment("This file is generated by the program.");
writer.WriteStartElement("root");
writer.WriteStartElement("OFBM");
writer.WriteAttributeString("time", "9:15");
writer.WriteAttributeString("date", "22.06.2016");
writer.WriteElementString("folder", #"file:///C:/Program Files (x86)/Cisco/Cisco AnyConnect Secure Mobility Client");
writer.WriteElementString("folder", #"file:///C:/Arduino223");
writer.WriteEndElement();
writer.WriteEndElement();
writer.WriteEndDocument();
writer.Flush();
writer.Close();
}
How do I also append new data? Instead of creating a new XML each time.
Add some settings to achieve the indent you are trying to accomplish in your XML file:
//I added this part (XmlWriterSettings):
XmlWriterSettings mySettings = new XmlWriterSettings();
mySettings.Indent = true;
mySettings.IndentChars = (" ");
mySettings.CloseOutput = true;
mySettings.OmitXmlDeclaration = true;
//Added the settings you intialize and set on your XmlWriter:
XmlWriter writer = XmlWriter.Create(#"C:\Users\Alek\Dropbox\D\Debug\product.xml", mySettings);
writer.WriteStartDocument();
writer.WriteComment("This file is generated by the program.");
writer.WriteStartElement("root");
writer.WriteStartElement("OFBM");
writer.WriteAttributeString("time", "9:15");
writer.WriteAttributeString("date", "22.06.2016");
writer.WriteElementString("folder", #"file:///C:/Program Files (x86)/Cisco/Cisco AnyConnect Secure Mobility Client");
writer.WriteElementString("folder", #"file:///C:/Arduino223");
writer.WriteEndElement();
//writer.WriteEndElement();
//writer.WriteEndDocument();
writer.Flush();
writer.Close();
To append new data without recreating the file, you can do this:
XDocument doc = XDocument.Load(#"C:\Users\Alek\Dropbox\D\Debug\product.xml");
XElement school = doc.Element("root");
school.Add(new XElement("OFBM",
new XElement("folder", "file:///C:/Arduino223")));
doc.Save(#"C:\Users\Alek\Dropbox\D\Debug\product.xml");

Append Serialized Object Into XML in C#

I have a XML structer like that
<?xml version="1.0" encoding="utf-8"?>
<Product>
<ProductName>da</ProductName>
<PluginPath></PluginPath>
<Instances></Instances>
</Product>
and i serialize my object to string.
<?xml version="1.0"?>
<Instance xmlns:xsi="http://bla bla" xmlns:xsd="bla bla" UniqueId="d4820029b7d7">
<InstanceName>Instance MyTestPluginForm</InstanceName>
<Description>Test Plugin IW</Description>
<AddedDate>2016-10-19T11:05:10.7443404+02:00</AddedDate>
<LogSettings>
<LoggingLevel>None</LoggingLevel>
<LogFilePath /><MaximumSize>100</MaximumSize
<ClearAfterDays>7</ClearAfterDays>
<IsSaveActiviesToEventLog>false</IsSaveActiviesToEventLog>
</LogSettings>
<ProductSpecific/>
</Instance>
So I want to append the second one in the Instances node in the first xml. But as you see both has xml definition on the top and after serializazion i got xmlns:xsi and xmlns:xsd attributes.
How to solve this problem?
PS: I do not want to create XML elements. Because my xml schema is dynamic. It has to be done with serialization. (I already checked this sample)
I solved the problem. using the code here
public static void CreateXmlFile(Instance instance, string filePath)
{
var xml = "<?xml version=\"1.0\" encoding=\"utf-8\"?><Product><ProductName>da</ProductName><PluginPath></PluginPath><Instances></Instances></Product>";
XmlDocument xmlDocument = new XmlDocument();
xmlDocument.LoadXml(xml);
xmlDocument.Save(filePath);
XmlNode xnode = xmlDocument.CreateNode(XmlNodeType.Element, "Instances", null);
XmlSerializer xSeriz = new XmlSerializer(typeof(Instance));
XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
ns.Add("", "");
XmlWriterSettings writtersetting = new XmlWriterSettings();
writtersetting.OmitXmlDeclaration = true;
StringWriter stringwriter = new StringWriter();
using (XmlWriter xmlwriter = System.Xml.XmlWriter.Create(stringwriter, writtersetting))
{
xSeriz.Serialize(xmlwriter, instance, ns);
}
xnode.InnerXml = stringwriter.ToString();
XmlNode bindxnode = xnode.SelectSingleNode("Instance");
xmlDocument.DocumentElement.SelectSingleNode("Instances").AppendChild(bindxnode);
xmlDocument.Save(filePath);
}

Remove encoding from XmlWriter

I'm using XmlWriter and XmlWriterSettings to write an XML file to disk. However, the system that is parsing the XML file is complaining about the encoding.
<?xml version="1.0" encoding="utf-8"?>
What it wants is this:
<?xml version="1.0" ?>
If I try OmitXmlDeclaration = true, then I don't get the xml line at all.
string destinationName = "C:\\temp\\file.xml";
string strClassification = "None";
XmlWriterSettings settings = new XmlWriterSettings();
settings.Indent = true;
using (XmlWriter writer = XmlWriter.Create(destinationName, settings))
{
writer.WriteStartDocument();
writer.WriteStartElement("ChunkData");
writer.WriteElementString("Classification", strClassification);
writer.WriteEndElement();
}
Just ran into this ---
remove the XmlWriterSettings() altogether and use the XmlTextWriter()'s Formatting field for indention.
pass in null for the Encoding argument of XmlTextWriter's ctor
The following code will create the output that you're looking for:
<?xml version="1.0" ?>
var w = new XmlTextWriter(filename, null);
w.Formatting = Formatting.Indented;
w.WriteStartDocument();
w.WriteStartElement("ChunkData");
w.WriteEndDocument();
w.Close();
The .Close() effectively creates the file - the using and Create() approach will also work.

Prevent XmlSerializer from formatting output

When using the default settings with the XmlSerializer it will output the XML as a formated value.
IE: something along these lines.
<?xml version="1.0" encoding="utf-8"?>
<ArrayOfStock xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Stock>
<ProductCode>12345</ProductCode>
<ProductPrice>10.32</ProductPrice>
</Stock>
<Stock>
<ProductCode>45632</ProductCode>
<ProductPrice>5.43</ProductPrice>
</Stock>
</ArrayOfStock>
How does one prevent any type of formatting on the output? So what I am looking to achieve is this.
<?xml version="1.0" encoding="utf-8"?><ArrayOfStock xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><Stock><ProductCode>123456</ProductCode><ProductPrice>10.57</ProductPrice></Stock><Stock><ProductCode>789123</ProductCode><ProductPrice>133.22</ProductPrice></Stock></ArrayOfStock>
EDIT: The full code of my method is
public static String Serialize(Stock stock)
{
XmlSerializer serializer = new XmlSerializer(typeof(Stock));
using (StringWriter stringWriter = new StringWriter())
{
serializer.Serialize(stringWriter, stock);
return stringWriter.ToString();
}
}
Not very intuitive, but the Indent property on the XmlWriterSettings controls the whole formatting:
var serializer = new XmlSerializer(typeof(MyClass));
using (var writer = new StreamWriter("file.path"))
using (var xmlWriter = XmlWriter.Create(writer, new XmlWriterSettings { Indent = false }))
{
serializer.Serialize(xmlWriter, myObject);
}
There are a few more options on XmlWriterSettings that you might want to explore.
It is simple to parse the resulting XML and remove and newlines and tabs...
using 'Indent = false', will still put elements on newlines no?
..
XmlSerializer xmlser = new XmlSerializer(...);
XmlWriterSettings settings = new XmlWriterSettings {Indent = false};
using (XmlWriter xw = XmlWriter.Create(stream, settings))
{
...

Categories

Resources