使用服务堆栈的格式正确的 XML

本文关键字:XML 格式 服务 堆栈 | 更新日期: 2023-09-27 18:33:46

我正在构建一个MVC5应用程序,该应用程序从数据库中提取记录并允许用户执行一些基本的数据清理编辑。

数据清理后,需要将其导出为XML,通过验证器运行,然后上传到第三方门户。

我正在使用 Service Stack,过去我发现它相当快速和直接,尤其是在输出到 CSV 时。

我遇到的一个问题是XML序列化程序。 我不确定如何让它生成格式良好的 XML。

我得到的文件只是将其转储到一行上,由于格式不正确,因此无法验证。

以下是我的控制器操作的摘录:

 Response.Clear();
 Response.ContentType = "text/xml";
 Response.AddHeader("Content-Disposition", "attachment; filename="myFile.xml"");
 XmlSerializer.SerializeToStream(viewModel, Response.OutputStream);
 Response.End();

更新:感谢您的有用评论,正如所解释的,我不是在谈论漂亮的打印,问题是我需要在将文件上传到第三方之前通过验证器运行文件。 验证程序抛出的错误消息是错误:0000,XML 格式不正确。一行上不能有多个标记。

使用服务堆栈的格式正确的 XML

首先,请注意,XML 中的大多数空格(包括换行符(都是无关紧要的 - 它没有任何意义,仅用于美化。 缺少新行不会使 XML 格式不正确。 请参阅 XML 文档或 https://www.w3.org/TR/REC-xml/#sec-white-space 中的空格。 因此,从理论上讲,ServiceStack的XmlSerializer是否将所有XML放在一行上并不重要。

话虽如此,如果出于某种原因,您必须将 XML 分解为多行,则需要做一些工作。 从源代码中我们可以看到,XmlSerializer使用带有硬编码静态XmlWriterSettingsDataContractSerializer,不允许设置XmlWriterSettings.Indent = true 。 但是,由于此类只是 Microsoft 数据协定序列化程序上的一个非常薄的包装器,因此您可以替换自己的代码:

public static class DataContractSerializerHelper
{
    private static readonly XmlWriterSettings xmlWriterSettings = new XmlWriterSettings { Indent = true, IndentChars = "  " };
    public static string SerializeToString<T>(T from)
    {
        try
        {
            using (var ms = new MemoryStream())
            using (var xw = XmlWriter.Create(ms, xmlWriterSettings))
            {
                var serializer = new DataContractSerializer(from.GetType());
                serializer.WriteObject(xw, from);
                xw.Flush();
                ms.Seek(0, SeekOrigin.Begin);
                var reader = new StreamReader(ms);
                return reader.ReadToEnd();
            }
        }
        catch (Exception ex)
        {
            throw new SerializationException(string.Format("Error serializing '"{0}'"", from), ex);
        }
    }
    public static void SerializeToWriter<T>(T value, TextWriter writer)
    {
        try
        {
            using (var xw = XmlWriter.Create(writer, xmlWriterSettings))
            {
                var serializer = new DataContractSerializer(value.GetType());
                serializer.WriteObject(xw, value);
            }
        }
        catch (Exception ex)
        {
            throw new SerializationException(string.Format("Error serializing '"{0}'"", value), ex);
        }
    }
    public static void SerializeToStream(object obj, Stream stream)
    {
        if (obj == null) 
            return;
        using (var xw = XmlWriter.Create(stream, xmlWriterSettings))
        {
            var serializer = new DataContractSerializer(obj.GetType());
            serializer.WriteObject(xw, obj);
        }
    }
}

然后做:

DataContractSerializerHelper.SerializeToStream(viewModel, Response.OutputStream);