使用 3 个级别序列化 XML 文档

问题描述

例如,我正在尝试以指定格式获取输出 预期

<?xml version="1.0"?>
<xml>
    <JournalEntries>
      <JournalEntry>
        <Field1>SampleOne</Field1>
        <Field2>SampleTwo</Field2>
      </JournalEntry>
      <JournalEntry>
        <Field1>SampleOne</Field1>
        <Field2>SampleTwo</Field2>
      </JournalEntry>
    </JournalEntries>
</xml>

我的当前输出

<?xml version="1.0"?>
<xml>
  <JournalEntry>
    <Field1>SampleOne</Field1>
    <Field2>SampleTwo</Field2>
  </JournalEntry>
  <JournalEntry>
    <Field1>SampleOne</Field1>
    <Field2>SampleTwo</Field2>
  </JournalEntry>
</xml>

所以基本上我需要添加一个 root ?从某种意义上说,在开始和结束处都有一个 JournalEntries。由于一组条目由多个条目组成

[XmlRoot(ElementName = "xml")]
    public class JournalDocument
    {
        
        public JournalDocument()
        {
        }

        public JournalDocument(UnProcessedDocument input)
        {
            input.Body.ForEach(o =>
            {
                JournalEntries.Add(new JournalEntry
                {
                    Field1 = "SampleOne"
                    Field2 = "SampleTwo"
                }); ;
            });
        }

        [XmlElement("JournalEntry")]
        public List<JournalEntry> JournalEntries { get; set; } = new List<JournalEntry>();
    }

    public class JournalEntry
    {
        public string Field1 {get;set;}

        public string Field2 {get;set}
    }

我不知道我是否将定义的根和元素放在正确的位置,我尝试移动它们但没有运气..例如,我尝试将 [XmlRoot(ElementName = "JournalEntries")] 放在我的 {{1} 上方}}类

解决方法

我更喜欢使用 IXmlSerializable。 它对我来说更灵活,并且可以让您更好地控制序列化。

示例:

public class JournalDocument : IXmlSerializable
    {
        public XmlSchema GetSchema() => null;
        public void WriteXml(XmlWriter writer)
        {
            writer.WriteStartDocument();
            writer.WriteStartElement("xml");
            writer.WriteStartElement("JournalEntries")
            if(this.JournalEntries.Count != 0)
            {
                foreach(JournalEntrie entrie in this.JournalEntries)
                {
                     writer.WriteStartElement("JournalEntrie");
                     writer.WriteElementString("Field1",entrie.Field1)
                     writer.WriteElementString("Field2",entrie.Field2)
                     writer.WriteEndElement();
                }
            }
            writer.WriteEndElement();
            writer.WriteEndDocument(); // close all open elements
        }
        public void ReadXml(XmlReader reader)
        {
            while(reader.Read())
            {
                if(reader.NodeType == XmlNodeType.element)
                {
                    JournalEntrie entrie;
                    switch(reader.Name)
                    {
                        case "JournalEntrie":
                            entrie = new JournalEntrie();
                            break;
                        case "Field1":
                            entire.Field1 = reader.ReadElementContentAsString();
                            break;

                       // Now make this for every element.
                    }
                }
            }
        }
    }
,

虽然 IXMLSerializer 是一个选项,但我最终还是创建了一个扩展方法

public static string Serialize<T>(this object obj)
        {
            XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
            ns.Add("","");
            var xmlWriterSettings = new XmlWriterSettings() { Indent = true };
            XmlSerializer serializer = new XmlSerializer(typeof(T));
            var stringWriter = new StringWriter();
            using var writer = XmlWriter.Create(stringWriter,xmlWriterSettings);
            serializer.Serialize(writer,obj,ns);
            writer.Close();
            return stringWriter.ToString();
        }

我的主要代码可以与 [XmlRoot(ElementName = "xml")] 保持不变,但只需删除 [XmlElement("JournalEntry")]

这最终解决了我的问题。