I want to create an XML document like this:
I want to create it from scratch using code and LINQ-to-XML. In the form Load Event I've written this code:
private void Form9_Load(object sender, EventArgs e)
{
doc = new XDocument(new XDeclaration("1.0", "utf-8", "yes"));
XElement myroot = new XElement("Employees");
doc.Add(myroot);
}
How I can add new person to Employees, and if I want to insert person in specific location what can I do?
How I can delete or update a specific person ?
Search element you want to add and use Add method as shown below
xDoc.Element("content")
.Elements("item")
.Where(item => item.Attribute("id").Value == "2").FirstOrDefault()
.AddAfterSelf(new XElement("item", "C", new XAttribute("id", "3")));
or
<Microsoft>
<DOTNet>
</DOTNet>
</Microsoft>
private void addToXml()
{
XDocument xmlDoc = XDocument.Load("yourfile.xml");
xmlDoc.Element("Microsoft").Add(new XElement("DOTNet", new XElement("Name", "Nisar"),
new XElement("Forum", "dotnetobject"), new XElement("Position", "Member")));
xmlDoc.Save("yourfile.xml");
readXml();
}
<Microsoft>
<DOTNet>
<Name>Nisar</Name>
<Forum>dotnetobject</Forum>
<Position>Member</Position>
</DOTNet>
</Microsoft>
Related
I'm creating a Windows Phone 8.1 app, and I need to serialize my data to XML.
I have two functions; the first one is creating a document where I can later put my retrieved data.
public async Task make()
{
using (var questions = await ApplicationData.Current.LocalFolder.OpenStreamForWriteAsync(
"data.xml",
CreationCollisionOption.OpenIfExists))
{
XDocument xml = new XDocument(
new XDeclaration("1.0", "utf-8", "yes"),
new XElement("Root")
);
xml.Save(questions);
}
}
The second one is making serialization to my xml file:
public async Task serial(Tsk tak)
{
using (var questions = await ApplicationData.Current.LocalFolder.OpenStreamForWriteAsync(
"data.xml",
CreationCollisionOption.OpenIfExists))
{
XDocument xml = XDocument.Load(questions);
xml.Root.Add(new XAttribute("Date", tak.Date),
new XElement("time", tak.Time),
new XElement("text", tak.Text)
);
xml.Save(questions);
}
}
The first xml function is making this code:
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<root />
When I'm running the second function I've got this error: root element is missing. Can anyone tell me how I can get this serialization to work?
Try this, you might need to doctor it a bit:
1) create the document
XmlDocument doc = new XmlDocument();
XmlElement root = doc.CreateElement("root");
doc.AppendChild(root);
file = await ApplicationData.Current.LocalFolder.CreateFileAsync("data.xml");
await FileIO.WriteTextAsync(file, doc.GetXml());
Debug.WriteLine("Done creating file.");
2) write the new data to the document
StorageFile file = await ApplicationData.Current.LocalFolder.GetFileAsync("data.xml");
XDocument doc = XDocument.Load(file.Path);
XElement newQuestion = new XElement("Question",
new XElement("time", tak.Time),
new XElement("text", tak.Text)
).SetAttributeValue("Date", tak.Date);
doc.Root.Add(newQuestion);
await FileIO.WriteTextAsync(file, doc.Root.ToString());
I have an XML in the following format
<Attachment>
<AttachmentName>Top Nav Menu.docx</AttachmentName>
<Subject>Attachment1</Subject>
<Sender>JameelM#orioninc.com</Sender>
</Attachment>
I want to attach another Attachment like above after the attachment close node. Below are the code that i have written for writing xml file
var doc = new XDocument(
new XDeclaration("1.0", "utf-16", "true"),
new XProcessingInstruction("test", "value"),
new XElement("Attachment",new XElement("AttachmentName", attachment.Name),
new XElement("Subject", exchangeEmailInformation.Subject),
new XElement("Sender", exchangeEmailInformation.Sender
)));
doc.Save(ConfigInformation.BackUpPath + FolderId[index]+"\\Attachments"+index+".xml");
Create root node for your attachments:
var doc = new XDocument(
new XDeclaration("1.0", "utf-16", "true"),
new XProcessingInstruction("test", "value"),
new XElement("Attachments",
new XElement("Attachment",
new XElement("AttachmentName", attachment.Name),
new XElement("Subject", exchangeEmailInformation.Subject),
new XElement("Sender", exchangeEmailInformation.Sender)
)));
When you decide to append another attachment, load document and add attachment to root:
doc.Root.Add(new XElement("Attachment",
new XElement("AttachmentName", attachment.Name),
new XElement("Subject", exchangeEmailInformation.Subject),
new XElement("Sender", exchangeEmailInformation.Sender)
));
I would use the XMLSerializer class. There you can handle your XML files just as if they are classes. Just have a look, you will like it :)
Load XML -> Use Classes in Code (modify, delete, add) -> Serialize back into XML
I work with XML documents that look like this:
All I need is extract the text between the tags. Since it's being successfully highlighted in black by a common XML editor, I'm assuming I should be able to extract it manually?
So far I've tried the following:
private void Form1_Load(System.Object sender, System.EventArgs e)
{
XmlDocument doc = new XmlDocument();
doc.Load("C:\\users\\admin\\desktop\\index.xml");
foreach (object node_loopVariable in doc.ChildNodes) {
node = node_loopVariable;
ProcNode(node);
}
}
private void ProcNode(XmlNode node)
{
Console.WriteLine(node.InnerText);
foreach (XmlNode subNode in node.ChildNodes) {
Console.WriteLine(subNode.InnerText);
}
}
Is that a reliable solution?
Use the XDocument class to read the XML and query it using LINQ to XML.
You can do something like that:
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(HttpContext.Current.Server.MapPath("App_Data/file.xml"));
XmlElement xelNo = xmlDoc.GetElementById("ElementID");
Then you can access the Attributes or Text of this Element;
But to use this you must know the ID of your element.
I am trying to create and XML file with data I am collecting, however for a particular I need multiple sub tags to be generated
So I wish to have something like this:-
<Feedbacks>
<Feedback>
<Name></Name>
<Surname></Surname>
<Images>
<Image></Image>
<Image></Image>
<Image></Image>
</Images>
</Feedback>
</Feedbacks>
Sorry do not know how to paste the correct XML file here, but I think you get the idea. At the moment I have this code that is working:-
private static void CreateFeedbackXMLFile()
{
XmlDocument doc = new XmlDocument();
XmlNode docNode = doc.CreateXmlDeclaration("1.0", "UTF-8", null);
doc.AppendChild(docNode);
XmlNode Node = doc.CreateElement("Feedbacks");
doc.AppendChild(Node);
string fileName = "Feedback.xml";
string filePath = Properties.Settings.Default.DefaultFolder + "\\" + fileName;
doc.Save(filePath);
}
public static void InsertFeedback(Feedback feedback)
{
CreateFeedbackXMLFile();
string filePath = Properties.Settings.Default.DefaultFolder + "\\Feedback.xml" ;
XDocument xmlDoc = XDocument.Load(filePath);
XElement XParentElement = new XElement("Feedback");
InsertIntoXMLDoc(feedback, filePath, xmlDoc);
}
private static void InsertIntoXMLDoc(Feedback feedback, string filePath, XDocument xmlDoc)
{
xmlDoc.Element("Feedbacks").Add(new XElement("Feedback",
new XElement("Name", feedback.Name),
new XElement("Surname", feedback.Surname),
new XElement("Email", feedback.Email),
new XElement("Website", feedback.Website),
new XElement("Suggestion", feedback.Suggestion),
new XElement("Error", feedback.Error),
new XElement("MailingList", feedback.MailingList),
new XElement("Comments", feedback.Comments)
));
}
xmlDoc.Save(filePath);
}
Now I need to loop through the imageList and create nodes according to how many images I have.
Thanks for your help and time
Looping is the way to go for what you are trying. In fact, there is no "loopless" way to achieve that. You can, however, disguise the loop as a LINQ query, with something like this:
xmlDoc.Element("Feedbacks").Add(
/* All the elements before your image list */
XElement("images",
from img in myImageList select new XElement(...)
)
/* All the elements after your image list, preceeded by a comma */
);
Of course, you'll need to replace myImageList with your actual collection of images. Note that if you have an ImageList control, the actual collection is not the control itself, but its Images property.
Also, on the ..., you'll need to put whatever logics you are using to create each node from an image (using the auto-typed local variable img to refer to the appropriate image for each node).
I have an XML document that contains the following structure:
Its more or less a collection of Events:
<Events>
<Event>
<DateTime></DateTime>
<EventType></EventType>
<Result></Result>
<Provider></Provider>
<ErrorMessage></ErrorMessage>
<InnerException></InnerException>
</Event>
</Events>
In C# I have a persistent object called Event:
Now given that the document already exists, and saved to file... I call :
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(dataPath);
Now how can I add a new Event item to events?
I've got a strongly typed Event item in my C# code, and want it inserted into the Events collection in the XML object as last child.
I guess this is what I am really asking : https://stackoverflow.com/questions/1457033/c-insert-a-strongly-typed-object-as-node-in-existing-xml-document
Take a look at the Xml Serialization attributes.
You can do this:
[XmlRoot("Event")]
public class Event
{
[XmlElement("DateTime")]
public string DateTime
{
get;
set;
}
[XmlElement("EventType")]
public EnumReportingEventType EventType
{
get;
set;
}
[XmlElement("Result")]
public EnumReportingResult Result
{
get;
set;
}
[XmlElement("Provider")]
public string Provider
{
get;
set;
}
[XmlElement("ErrorMessage")]
public string ErrorMessage
{
get;
set;
}
[XmlElement("InnerException")]
public string InnerException
{
get;
set;
}
}
In fact, if the properties of your class have the same name as the elements in your Xml, you do not have to use the XmlElement attributes.
Then, you can use the XmlSerializer to serialize and deserialize.
Edit:
Then, wouldn't it be better to create a type which represent the entire type that is stored in the existing xml ?
Deserialize it, give a value to the additional property, and serialize it back ?
Just hand code it using the XmlDocument. You can add a class that does the conversion or insertion into the document you are going to save.
This is based on the restriction of .net 2.0 and what you said in these comments:
#Fred, I want to try minimize the write time, hence the reason for not writing all at once, the less write time in this app, the less chance of file corruption. – JL 16 mins ago
Why do you think you have a lot of chance of file corruption ? – Frederik Gheysels 9 mins ago
From existing test results on code I already have using serialization as a whole.
If you are using .Net 3.5 you can use Linq to XML, something like the following will work
XDocument doc = new XDocument(
new XDeclaration("1.0", "utf-8", "yes"),
new XComment("Event document"),
new XElement("Events",
new XElement ("Event",
new XElement("DateTime", event.DateTime),
new XElement("EventType", event.EventType),
new XElement("Result", event.Result),
new XElement("Provider", event.Provider),
new XElement("ErrorMessage", event.ErrorMessage),
new XElement("InnerException", event.InnerException)
)
));
doc.Save(#"c:\sample.xml");
If you have an existing xml document that you want to append to somthing like the following is required.
XDocument doc = XDocument.Load(#"c:\sample.xml");
XElement events = doc.Element(XName.Get("Events"));
events.Add(new XElement ("Event",
new XElement("DateTime", event.DateTime),
new XElement("EventType", event.EventType),
new XElement("Result", event.Result),
new XElement("Provider", event.Provider),
new XElement("ErrorMessage", event.ErrorMessage),
new XElement("InnerException", event.InnerException)
));
doc.Save(#"c:\sample.xml");
Insert a XmlElement field near the end of the "Event" class like so:
[System.Xml.Serialization.XmlAnyElementAttribute()]
public System.Xml.XmlElement Any { get; set }
You can name it whatever you want as long as you have the "XmlAnyElementAttribute" on it.
You can use something like the following to serialize a strongly-typed object into this field:
MyParentObject parent = new MyParentObject(){ ... };
MyObject obj = new MyObject(){ /*... initialize*/ };
XmlSerializer ser = new XmlSerializer(typeof(MyObject));
XmlDocument doc = new XmlDocument();
using (StringWriter sw = new StringWriter())
{
ser.Serialize(sw, obj);
doc.LoadXml(sw.ToString());
}
parent.Any = (XmlElement)doc.DocumentElement;
The serialized XML will append nicely to your class, it will event include the correct namespaces.
Assuming that your Event class can already be serialized the way you want using XmlSerializer, you can do the following:
XmlSerializer ser = new XmlSerializer(typeof(Event));
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(dataPath);
Event evt = ...;
XmlDocument evtDoc = new XmlDocument();
using (XmlWriter writer = evtDoc.CreateNavigator().AppendChild())
{
ser.Serialize(writer, evt);
}
XmlNode evtNode = evtDoc.RemoveChild(evtDoc.DocumentElement);
XmlNode events = xmlDoc.SelectSingleNode("/Events");
events.AppendChild(evtNode);
What you are looking to do is something like:
doc.ChildNode[0].AppendChild(MethodToReturnADeserializedObject(event));
Create a method to deserialize the event object into an xml node. Then use AppendChild to insert that as the last element amongst it's child nodes.