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 ?
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.
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:
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.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.