I have code that serializes a complex object to XML and saves it as a file, is there a quick way to include a style sheet in the xml during the serialization?
Using C# and .net framework v2.
Link the XSL Style Sheet to the XML Documentxml version="1.0" encoding="UTF-8"?> <? xml-stylesheet type="text/xsl" href="cdcatalog.
Extensible Stylesheet Language Transformations (XSLT) is an XML-based language used, in conjunction with specialized processing software, for the transformation of XML documents.
You can use an XmlWriter
and WriteProcessingInstruction
:
XmlSerializer s = new XmlSerializer(typeof(myObj));
using (XmlWriter w = XmlWriter.Create(@"c:\test.xml"))
{
w.WriteProcessingInstruction("xml-stylesheet", "type=\"text/xsl\" href=\"USED-FILE.xsl\"");
s.Serialize(w, myObj);
}
For those who are wondering how to achieve similar things in modern dotnet core you gonna need to make few adjustments:
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Xml;
using System.Xml.Serialization;
using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Formatters;
using Microsoft.Extensions.DependencyInjection;
namespace ContentNegotiation
{
public class Program
{
public static void Main(string[] args) => CreateWebHostBuilder(args).Build().Run();
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>();
}
public class MyXmlSerializerOutputFormatter : XmlSerializerOutputFormatter
{
protected override void Serialize(XmlSerializer xmlSerializer, XmlWriter xmlWriter, object value)
{
// TODO: add me only if controller has some kind of custom attribute with XSLT file name
xmlWriter.WriteProcessingInstruction("xml-stylesheet", "type=\"text/xsl\" href=\"template.xsl\"");
base.Serialize(xmlSerializer, xmlWriter, value);
}
}
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc(options =>
{
options.RespectBrowserAcceptHeader = true; // default is false
// options.OutputFormatters.Add(new XmlSerializerOutputFormatter()); // not enough
options.OutputFormatters.Add(new MyXmlSerializerOutputFormatter());
})
// .AddXmlSerializerFormatters() // does not added by default, but not enough
.SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.UseStaticFiles();
app.UseMvc();
}
}
public class Post
{
public int Id { get; set; }
public string Title { get; set; }
public string Body { get; set; }
}
[ApiController]
public class DemoController : ControllerBase
{
// curl -k -i -s -H 'Accept: text/xml' http://localhost:5000/posts
// curl -k -i -s -H 'Accept: application/json' http://localhost:5000/posts
[HttpGet]
[Route(nameof(Posts))]
public IEnumerable<Post> Posts() => new[] {
new Post {
Id = 1,
Title = "Hello World",
Body = "Lorem ipsum dot color"
},
new Post {
Id = 2,
Title = "Post 2",
Body = "Lorem ipsum dot color"
}
};
}
}
We are turning on content negotiation in ConfigureServices and giving our implementation of XmlSerializerOutputFormatter which will add XSL to the output
So now our backend will respond with JSON to requests like:
curl -k -i -s -H 'Accept: application/json' http://localhost:5000/posts
and XML:
curl -k -i -s -H 'Accept: text/xml' http://localhost:5000/posts
Sample of xsl for demo purposes might be found here: https://mac-blog.org.ua/dotnet-content-negotiation/
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With