使用服务堆栈生成良好的XML

时间:2016-02-08 16:51:23

标签: c# xml asp.net-mvc-5 xml-serialization servicestack-text

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

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

我正在使用服务堆栈,过去我发现它相当快速和简单,特别是在输出到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格式不正确。一行不能有多个标签。

1 个答案:

答案 0 :(得分:2)

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

话虽如此,如果由于某种原因你必须美化地将你的XML分成多行,你需要做一些工作。从source code我们可以看到#create this so we have validation data newline <- c( 51.05837, 6.857822) newobs <- rbind(obs, newline) library(sqldf) looked_up<-function(data, lookup){ data<-sqldf("select A.*,B.segment from data A left join lookup B ON (A.longitude >= B.lon_min and A.longitude <= B.lon_max and A.latitude >= B.lat_min and A.latitude <= B.lat_max) ") data } looked_up(newobs, seg) #RESULTS longitude latitude segment 1 52.06264 6.412816 <NA> 2 52.06097 6.413106 <NA> 3 51.06097 6.413346 <NA> 4 54.06097 6.413276 <NA> 5 51.06089 6.413114 <NA> 6 52.05444 6.413094 <NA> 7 51.05837 6.857822 01a 使用DataContractSerializer使用了不允许设置XmlWriterSettings的硬编码静态XmlWriterSettings.Indent = true。但是,由于此类只是Microsoft数据协定序列化程序的一个非常薄的包装器,因此您可以替换自己的代码:

XmlSerializer

然后做:

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);
        }
    }
}