C #, вставьте строго типизированный объект в XML-документ как элемент - PullRequest
2 голосов
/ 22 сентября 2009

У меня есть документ 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);

Теперь, как я могу добавить новый элемент Event к событиям?

У меня есть строго типизированный элемент Event в моем коде C #, и я хочу вставить его в коллекцию Events в объекте XML как последний дочерний элемент.

Я думаю, это то, что я действительно спрашиваю: https://stackoverflow.com/questions/1457033/c-insert-a-strongly-typed-object-as-node-in-existing-xml-document

Ответы [ 6 ]

3 голосов
/ 22 сентября 2009

Посмотрите на атрибуты сериализации 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 для сериализации и десериализации.

Edit: Тогда не лучше ли создать тип, который будет представлять весь тип, хранящийся в существующем xml?
Десериализовать его, присвоить значение дополнительному свойству и сериализовать обратно?

1 голос
/ 22 сентября 2009

Предполагая, что ваш класс 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);
1 голос
/ 22 сентября 2009

Просто закодируйте его вручную с помощью XmlDocument. Вы можете добавить класс, который выполняет преобразование или вставку в документ, который вы собираетесь сохранить.

Это основано на ограничении .net 2.0 и на том, что вы сказали в этих комментариях:

  • @ Фред, я хочу попытаться минимизировать время записи, поэтому причина не одновременной записи: чем меньше время записи в этом приложении, тем меньше вероятность повреждения файла. - JL 16 минут назад
  • Почему, по вашему мнению, у вас много шансов на повреждение файлов? - Фредерик Гейселс 9 минут назад
  • Исходя из существующих результатов тестирования кода, я уже использовал сериализацию в целом.
1 голос
/ 22 сентября 2009

Вставьте поле XmlElement ближе к концу класса «Event», например:

[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 будет хорошо добавляться к вашему классу, он будет включать в себя правильные пространства имен.

1 голос
/ 22 сентября 2009

Если вы используете .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");
0 голосов
/ 22 сентября 2009

То, что вы хотите сделать, это что-то вроде:

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

Создать метод для десериализации объекта события в узел xml. Затем используйте AppendChild, чтобы вставить его как последний элемент среди его дочерних узлов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...