Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Possible to add a XSLT Stylesheet to a serialized XML document?

Tags:

c#

xml

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.

like image 232
JL. Avatar asked Sep 22 '09 16:09

JL.


People also ask

How do you link an XSLT stylesheet to an XML document?

Link the XSL Style Sheet to the XML Documentxml version="1.0" encoding="UTF-8"?> <? xml-stylesheet type="text/xsl" href="cdcatalog.

Is XSLT a XML document?

Extensible Stylesheet Language Transformations (XSLT) is an XML-based language used, in conjunction with specialized processing software, for the transformation of XML documents.


2 Answers

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);
    }
like image 134
bruno conde Avatar answered Sep 20 '22 20:09

bruno conde


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

dotnet core content negotiation plus xsl

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/

like image 21
mac Avatar answered Sep 18 '22 20:09

mac