代码之家  ›  专栏  ›  技术社区  ›  JL. Hans Passant

c,将强类型对象作为元素插入到XML文档中

  •  2
  • JL. Hans Passant  · 技术社区  · 15 年前

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

    它或多或少是一组事件:

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

    在C中,我有一个称为事件的持久对象:

    既然文档已经存在,并保存到文件中…我称之为:

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

    现在,如何向事件添加新的事件项?

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

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

    6 回复  |  直到 15 年前
        1
  •  1
  •   eglasius    15 年前

    只需使用XML文档手工编码即可。可以向要保存的文档中添加进行转换或插入的类。

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

    • @Fred,我想尽量缩短写时间,因此不能一次全部写,这个应用程序的写时间越短,文件损坏的可能性就越小。16分钟前
    • 为什么你认为你有很大的机会破坏文件?9分钟前的Frederik Gheysels
    • 从代码的现有测试结果来看,我已经整体上使用了序列化。
        2
  •  3
  •   Frederik Gheysels    15 年前

    查看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中的整个类型的类型会更好吗?
    反序列化它,给附加属性一个值,然后序列化它?

        3
  •  1
  •   Simon Fox    15 年前

    如果您使用的是.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文档要附加到somthing,则需要如下内容。

    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");
    
        4
  •  1
  •   Blue Toque    15 年前

    在“event”类的末尾插入一个xmlement字段,如下所示:

    [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将很好地附加到类中,它将事件包括正确的名称空间。

        5
  •  1
  •   Pavel Minaev    15 年前

    假设你的 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);
    
        6
  •  0
  •   mhenrixon    15 年前

    你要做的是:

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

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