C#,将强类型对象作为Element插入XML Document

时间:2009-09-21 20:51:30

标签: c# xml

我有一个包含以下结构的XML文档:

它或多或少是一系列事件:

<Events>
  <Event>
    <DateTime></DateTime>
    <EventType></EventType>
    <Result></Result>
    <Provider></Provider>
    <ErrorMessage></ErrorMessage>
    <InnerException></InnerException>
  </Event>
</Events>

在C#中,我有一个名为Event的持久对象:

现在假定文档已经存在,并保存到文件中...我打电话:

        XmlDocument xmlDoc = new XmlDocument();
        xmlDoc.Load(dataPath);

现在我如何向活动添加新的活动项目?

我的C#代码中有一个强类型的事件项,并希望它作为最后一个子项插入到XML对象的Events集合中。

我想这就是我真正要问的问题:https://stackoverflow.com/questions/1457033/c-insert-a-strongly-typed-object-as-node-in-existing-xml-document

6 个答案:

答案 0 :(得分:3)

查看Xml序列化属性。

你可以这样做:

[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;
    }
}

实际上,如果类的属性与Xml中的元素具有相同的名称,则不必使用XmlElement属性。

然后,您可以使用XmlSerializer来序列化和反序列化。

编辑: 那么,创建一个表示存储在现有xml中的整个类型的类型不是更好吗? 对它进行反序列化,为附加属性赋值,并将其序列化回来?

答案 1 :(得分:1)

如果您使用的是.Net 3.5,则可以使用Linq to XML,类似以下内容将起作用

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");

如果您有一个现有的xml文档要附加到类似下面的内容。

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");

答案 2 :(得分:1)

在“Event”类的末尾附近插入一个XmlElement字段,如下所示:

[System.Xml.Serialization.XmlAnyElementAttribute()]
public System.Xml.XmlElement Any { get; set }

只要你有“XmlAnyElementAttribute”,就可以任意命名。

您可以使用以下内容将强类型对象序列化到此字段中:

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;

序列化的XML将很好地附加到您的类,它将包含正确的名称空间。

答案 3 :(得分:1)

只需使用XmlDocument手动编码即可。您可以添加一个类来执行转换或插入要保存的文档。

这是基于.net 2.0的限制以及您在这些评论中所说的内容:

  • @Fred,我想尝试最小化写入时间,因此不能一次写入所有内容的原因是,此应用程序中的写入时间越少,文件损坏的可能性就越小。 - JL 16分钟前
  • 为什么你认为你有很多文件损坏的机会? - Frederik Gheysels 9分钟前
  • 从现有的代码测试结果中我已经使用了序列化作为一个整体。

答案 4 :(得分:1)

假设您的Event课程已经按照XmlSerializer的方式进行了序列化,您可以执行以下操作:

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);

答案 5 :(得分:0)

您要做的是:

doc.ChildNode[0].AppendChild(MethodToReturnADeserializedObject(event));

创建一个方法,将事件对象反序列化为xml节点。然后使用AppendChild将其作为其子节点中的最后一个元素插入。