将 C# 类序列化为保持结构的 XML

问题描述 投票:0回答:0

我收到了 4 个 XSD 架构文件(一个是根,一个用于标题/尾部,一个用于基础,一个用于元素类型)

将根传递给 xsd.exe,根据 XSD 成功生成具有适当结构的类,

我们现在可以为这些类的对象赋值并填充它们,问题是我们如何将它们序列化为保持原始结构的 XML 输出?

完整代码:

using System;
using System.IO;
using System.Xml;
using System.Xml.Schema;
using System.Diagnostics;
using System.Xml.Serialization;
using System.Data;
using System.Data.SqlClient;
using System.Collections.Generic;
using System.Reflection;
using System.Linq;
using GenericNamespace;

namespace ECDS
{
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                String WorkingDir = @"C:\cdsxml\XML";
                String FileName = "C:\\Program Files (x86)\\Microsoft SDKs\\Windows\\v10.0A\\bin\\NETFX 4.8 Tools\\xsd.exe";
                String ECDSConection = "you can use some dummy string data";
                //Generate class at runtime from xsd
                var p = new Process{StartInfo = {FileName = FileName, WorkingDirectory = WorkingDir, Arguments = "CDS-XML_Message_Root-V6-2-3.xsd /c /n:GenericNamespace"}};
                p.Start();
                p.WaitForExit();
                DataTable dataTable = new DataTable();
                using (SqlConnection connection = new SqlConnection(ECDSConection))
                {
                    connection.Open();
                    using (SqlCommand command = new SqlCommand("SELECT top (1) " + "[AmbulanceCallIdentifier]" + ",[NHSNumber]" + "FROM [dbo].[ecdsDummy]", connection))
                    {
                        {
                            SqlDataAdapter adapter = new SqlDataAdapter(command);
                            adapter.Fill(dataTable);
                        }
                    }

                    object obj = null;
                    // Create a list to store all the objects
                    List<object> objects = new List<object>();
                    // Loop through all the classes in the namespace GeneratedClasses
                    foreach (DataRow row in dataTable.Rows)
                    {
                        foreach (Type generatedclasses in Assembly.GetExecutingAssembly().GetTypes())
                        {
                            if (generatedclasses.Namespace == "GenericNamespace" && generatedclasses.IsClass)
                            {
                                // Check if the generated class has any public properties with a data type other than XmlElement or XmlDocument
                                bool hasNonXmlProperties = generatedclasses.GetProperties().Any(p => p.PropertyType != typeof(XmlElement) && p.PropertyType != typeof(XmlDocument));
                                if (!hasNonXmlProperties)
                                {
                                    continue;
                                }

                                // Check if an object with the same type and values already exists in the list
                                if ((objects.Any(o => o.GetType() == typeof(CDSXMLInterchange) && generatedclasses.Name == "CDSXMLInterchange" && CompareObjectValues(o, row))))
                                     )
                                {
                                    continue;
                                }

                                // Get the data from the dataTable and assign it to the generated class
                                obj = Activator.CreateInstance(generatedclasses);
                                try
                                {
                                    foreach (PropertyInfo property in generatedclasses.GetProperties())
                                    {
                                        if (row.Table.Columns.Contains(property.Name))
                                        {
                                            object value = row[property.Name];
                                            property.SetValue(obj, value);
                                        }
                                    }

                                    {
                                        objects.Add(obj);
                                    }
                                }
                                catch (Exception ex)
                                {
                                    ex.Message.ToString();
                                }
                            // }
                            }
                        }
                    }

                    // Get all types in the GeneratedClasses namespace
                    Type[] generatedTypes = Assembly.GetExecutingAssembly().GetTypes().Where(t => t.Namespace == "GenericNamespace").ToArray();
                    // Define the list of expected types
                    List<Type> expectedTypes = new List<Type>();
                    foreach (Type type in generatedTypes)
                    {
                        expectedTypes.Add(type);
                    }

                    // Create the XmlSerializer with the expected types
                    XmlSerializer serializer = new XmlSerializer(typeof(object), expectedTypes.ToArray());
                    //XmlSerializer serializer = new XmlSerializer(typeof(object), new XmlRootAttribute("CDSXMLInterchange"));
                    // Create the XmlSerializerNamespaces object with an empty namespace prefix and URI
                    XmlSerializerNamespaces serializerNamespaces = new XmlSerializerNamespaces();
                    serializerNamespaces.Add("", "");
                    //Serialize the objects to XML
                    XmlWriterSettings settings = new XmlWriterSettings();
                    settings.ConformanceLevel = ConformanceLevel.Fragment;
                    using (XmlWriter writer = XmlWriter.Create("C:\\cdsxml\\XMLTest.xml", settings))
                    {
                        foreach (object obj1 in objects)
                        {
                            Type objType = obj1.GetType();
                            string objTypeName = objType.Name;
                            string objNamespace = null;
                            XmlRootAttribute xmlRoot = objType.GetCustomAttribute<XmlRootAttribute>();
                            if (xmlRoot != null)
                            {
                                //RootElemet
                                objNamespace = objType.Namespace;
                                writer.WriteStartElement(objTypeName, "http://www.nhsia.nhs.uk/DataStandards/XMLschema/CDS/ns");
                                serializer.Serialize(writer, obj1, serializerNamespaces);
                            }
                            else
                            {
                                objNamespace = objType.Namespace;
                                writer.WriteStartElement(objTypeName, "http://www.nhsia.nhs.uk/DataStandards/XMLschema/CDS/ns");
                                //writer.WriteStartElement("ns", objTypeName, "http://www.nhsia.nhs.uk/DataStandards/XMLschema/CDS/ns");
                                //// Serialize objects to XML
                                serializer.Serialize(writer, obj1, serializerNamespaces);
                                // Write the end element
                                writer.WriteEndElement();
                            }
                        }

                        writer.WriteEndElement();
                    }
                }
            }
            catch (Exception ex)
            {
                ex.Message.ToString();
            }
        }

        // Helper method to compare the values of two objects
        public static bool CompareObjectValues(object obj, DataRow row)
        {
            foreach (PropertyInfo property in obj.GetType().GetProperties())
            {
                if (property.PropertyType.Namespace == "System")
                {
                    if (row.Table.Columns.Contains(property.Name))
                    {
                        object value = row[property.Name];
                        if (value is DBNull)
                        {
                            value = null;
                        }
                        else if (property.PropertyType == typeof(string[]))
                        {
                            value = ((string)value).Split(',');
                        }
                        else if (property.PropertyType == typeof(decimal))
                        {
                            decimal decimalValue;
                            if (!decimal.TryParse((string)value, out decimalValue))
                            {
                                Console.WriteLine("Unable to convert " + value + " to decimal.");
                                continue;
                            }

                            value = decimalValue;
                        }
                        else if (property.PropertyType == typeof(object) && (value is XmlElement || value is XmlDocument))
                        {
                            // Skip setting the property for <anyType> elements
                            continue;
                        }

                        if (!object.Equals(property.GetValue(obj), value))
                        {
                            return false;
                        }
                    }
                }
            }

            return true;
        }
    }
}

问题是,是否有任何直接的方法可以将对象序列化为 XML 而无需循环遍历它们并将开始元素/结束元素手动插入到输出 XML 中?这样做是在改变 XML 结构。

完整代码小提琴

XSD 文件

c# xml xsd xml-serialization xml-generation
© www.soinside.com 2019 - 2024. All rights reserved.