I have a program that creates an XML log. First I check if the XML exists, and if not I use the following code to create it:
XmlWriterSettings settings = new XmlWriterSettings();
settings.Indent = true;
using (XmlWriter writer = XmlWriter.Create(myXMLLog, settings))
{
writer.WriteStartDocument();
writer.WriteComment("Comment here.");
writer.WriteStartElement("Batch");
writer.WriteAttributeString("ID", BatchID);
writer.WriteAttributeString("Date", now);
writer.WriteStartElement("Step");
writer.WriteElementString("Name", step);
writer.WriteElementString("Success", success);
writer.WriteElementString("Message", message);
writer.WriteStartElement("Transaction");
writer.WriteElementString("ID", transID);
writer.WriteElementString("Details", details);
writer.WriteEndElement();
writer.WriteEndDocument();
}
This works as expected and creates the file:
<!--This log was created by the Application.-->
<Batch Date="1/22/2014 10:01:11 PM" ID="166bf0d2-3bd4-4353-b309-20b6d0d59a93">
<Step>
<Name>Start Batch</Name>
<Success>1</Success>
<Message>Processing Batch</Message>
<Transaction>
<ID>N/A</ID>
<Details>N/A</Details>
</Transaction>
</Step>
So the second time around, it checks that the XML exists, it does, so instead of creating it should just add to it. I'm using the following code for this:
XDocument xmlDoc = XDocument.Load(myXMLLog);
XElement root = new XElement("Batch");
root.Add(new XAttribute("ID", BatchID));
root.Add(new XAttribute("Date", now));
root.Add(new XElement("Step"));
root.Add(new XAttribute("Name", step));
root.Add(new XAttribute("Success", success));
root.Add(new XAttribute("Message", message));
root.Add(new XElement("Transaction"));
root.Add(new XAttribute("ID", transID));
root.Add(new XAttribute("Details", details));
xmlDoc.Element("Batch").Add(root);
xmlDoc.Save(myXMLLog);
So now I'm expecting the XML file to look something like this:
<!--This log was created by the Application.-->
<Batch Date="1/22/2014 10:01:11 PM" ID="166bf0d2-3bd4-4353-b309-20b6d0d59a93">
<Step>
<Name>Start Batch</Name>
<Success>1</Success>
<Message>Processing Batch</Message>
<Transaction>
<ID>N/A</ID>
<Details>N/A</Details>
</Transaction>
</Step>
</Batch>
<Batch Date="1/22/2014 10:20:00 PM" ID="166bf0d2-3bd4-4353-b309-20b6d0d5aaa">
<Step>
<Name>Start Batch</Name>
<Success>1</Success>
<Message>Processing Batch</Message>
<Transaction>
<ID>N/A</ID>
<Details>N/A</Details>
</Transaction>
</Step>
</Batch>
But instead I get an exception "Duplicate Attribute".
What am I doing wrong?
Thanks!
EDIT:
The XML Document does has at the top of it. Valid XML would be very nice, but not a most.
EDIT EDIT:
This is how my code looks now:
if (File.Exists(myXMLLog))
{
XDocument xmlDoc = XDocument.Load(myXMLLog);
XElement root = new XElement("Batch",
new XAttribute("ID", BatchID),
new XAttribute("Date", now),
new XElement("Step",
new XElement("Name", step),
new XElement("Success", success),
new XElement("Message", message),
new XElement("Transaction",
new XAttribute("IDTrans", transID),
new XAttribute("Details", details))));
xmlDoc.Root.Add(root);
xmlDoc.Save(myXMLLog);
}
else
{
using (XmlWriter writer = XmlWriter.Create(myXMLLog, settings))
{
writer.WriteStartDocument();
writer.WriteComment("This log was created by the Application.");
writer.WriteStartElement("Batch");
writer.WriteAttributeString("ID", BatchID);
writer.WriteAttributeString("Date", now);
writer.WriteStartElement("Step");
writer.WriteElementString("Name", step);
writer.WriteElementString("Success", success);
writer.WriteElementString("Message", message);
writer.WriteStartElement("Transaction");
writer.WriteElementString("IDTrans", transID);
writer.WriteElementString("Details", details);
writer.WriteEndElement();
writer.WriteEndDocument();
}
}
I'm ok with the format of the XML, my problem now is that is doing the BATCH inside the first BATCH
<Batch Date="1/22/2014 11:49:17 PM" ID="6966578b-b326-4f16-a315-1b4228a9fa42">
<Step><Name>Create DataTable</Name>
<Success>1</Success>
<Message>DataTable was Created and Populated</Message>
<Transaction>
<IDTrans>N/A</IDTrans>
<Details>0</Details>
</Transaction>
</Step>
<Batch Date="1/22/2014 11:49:17 PM" ID="6966578b-b326-4f16-a315-1b4228a9fa42">
<Step>
<Name>Send Email</Name>
<Success>1</Success>
<Message>Template Seleted and Filled</Message>
<Transaction Details="Email To: email@email.com Link: " IDTrans="243b0a3c-d8b7-49c3-b1d0-asdfsdsdfsdf"/>
</Step>
</Batch>.....
EDIT FINAL
Working Code, combination of all answers:
if (File.Exists(myXMLLog))
{
XDocument xmlDoc = XDocument.Load(myXMLLog);
XElement root = new XElement("Batch",
new XAttribute("ID", BatchID),
new XAttribute("Date", now),
new XElement("Step",
new XElement("Name", step),
new XElement("Success", success),
new XElement("Message", message),
new XElement("Transaction",
new XAttribute("IDTrans", transID),
new XAttribute("Details", details))));
xmlDoc.Root.Add(root);
xmlDoc.Save(myXMLLog);
}
else
{
using (XmlWriter writer = XmlWriter.Create(myXMLLog, settings))
{
writer.WriteStartDocument();
writer.WriteComment("This log was created by the Application.");
writer.WriteStartElement("Root");
writer.WriteStartElement("Batch");
writer.WriteAttributeString("ID", BatchID);
writer.WriteAttributeString("Date", now);
writer.WriteStartElement("Step");
writer.WriteElementString("Name", step);
writer.WriteElementString("Success", success);
writer.WriteElementString("Message", message);
writer.WriteStartElement("Transaction");
writer.WriteElementString("IDTrans", transID);
writer.WriteElementString("Details", details);
writer.WriteEndElement();
writer.Flush();
writer.WriteEndDocument();
}
}
I'm happy with the results. If anyone has suggestions on how to better format the XML, please do so. Thanks everyone.
Your current code adds all these elements and attributes to root
, instead of adding some attributes to newly created elements.
Element creation should look like that:
XElement root = new XElement("Batch",
new XAttribute("ID", BatchID),
new XAttribute("Date", now),
new XElement("Step",
new XElement("Name", step),
new XElement("Success", success),
new XElement("Message", message),
new XElement("Transaction",
new XElement("ID", transID),
new XElement("Details", details))));