D.Mac February 2016

Well Formed XML using Service Stack

I'm building an MVC5 application which pulls records from a database and allows a user to perform some basic data cleansing edits.

Once the data has been cleansed it needs to be exported as XML, run through a validator and then uploaded to a third party portal.

I'm using Service Stack, and I've found it fairly quick and straightforward in the past, particularly when outputting to CSV.

The one issue I'm having is with the XML serialzer. I'm not sure how to make it generate well formed XML.

The file that i'm getting simply dumps it on one line, which won't validate because it isn't well formed.

below is an extract from my controller action:

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

UPDATE: Thanks for the useful comments, as explained I'm not talking about pretty printing, the issue is I need to run the file through a validator before uploading it to a third party. The error message the validator is throwing is Error:0000, XML not well-formed. Cannot have more than one tag on one line.

Answers


dbc February 2016

Firstly, be aware that most white space (including new lines) in XML is insignificant -- it has no meaning, and is only for beautification. The lack of new lines doesn't make the XML ill-formed. See White Space in XML Documents or https://www.w3.org/TR/REC-xml/#sec-white-space. Thus in theory it shouldn't matter whether ServiceStack's XmlSerializer is putting all of your XML on a single line.

That being said, if for whatever reason you must cosmetically break your XML up into multiple lines, you'll need to do a little work. From the source code we can see that XmlSerializer uses DataContractSerializer with a hardcoded static XmlWriterSettings that does not allow for setting XmlWriterSettings.Indent = true. However, since this class is just a very thin wrapper on Microsoft's data contract serializer, you can substitute your own code:

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 Mem 


D.Mac February 2016

Thanks to dbc for taking the time to look into this and post an aswer. However his solution seems like quite a lot of work to produce something so simple as a multi-line XML file.

I've modified an answer taken from this question:

What is the simplest way to get indented XML with line breaks from XmlDocument?

This is how my controller now looks

public string ExportXML()
    {            
        List<myDTO> viewModel = Mapper.Map<List<myDTO>>(myService.ExportXML());

        Response.ContentType = "text/xml";
        Response.AddHeader("Content-Disposition", "attachment; filename='myFile.xml'");
        Response.Clear();

        string xml = XmlSerializer.SerializeToString(viewModel);
        try
        {
            XDocument doc = XDocument.Parse(xml);
            return doc.ToString();
        }
        catch (Exception)
        {
            return xml;
        }
    }

This works really well and produces the file in the format that I require. I just thought there might be a simpler way to do it with service-stack.

Post Status

Asked in February 2016
Viewed 1,796 times
Voted 14
Answered 2 times

Search




Leave an answer