Можно добавить таблицу стилей XSLT в сериализованный документ XML? - PullRequest
19 голосов
/ 22 сентября 2009

У меня есть код, который сериализует сложный объект в XML и сохраняет его в виде файла. Есть ли быстрый способ включить таблицу стилей в XML во время сериализации?

Использование C # и .net framework v2.

Ответы [ 4 ]

30 голосов
/ 22 сентября 2009

Вы можете использовать XmlWriter и 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);
    }
0 голосов
/ 03 ноября 2018

Для тех, кто интересуется, как добиться схожих результатов в современном ядре dotnet, вам нужно внести несколько изменений:

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

Мы включаем согласование содержимого в ConfigureServices и даем нашу реализацию XmlSerializerOutputFormatter, которая добавит XSL к выводу

dotnet core content negotiation plus xsl

Так что теперь наш бэкэнд будет отвечать JSON на запросы вроде:

curl -k -i -s -H 'Accept: application/json' http://localhost:5000/posts

и XML:

curl -k -i -s -H 'Accept: text/xml' http://localhost:5000/posts

Образец xsl для демонстрационных целей можно найти здесь: https://mac -blog.org.ua / dotnet-content -gotiation /

0 голосов
/ 12 сентября 2018

Я написал это, чтобы свести проблему к простому добавлению атрибута в класс, как мы описываем все остальные директивы конструкции xml:

Использование будет:

    [XmlStylesheet("USED-FILE.xsl")]
    public class Xxx
    {
        // etc
    }


    Xxx x = new Xxx();

    XmlSerializer s = new XmlSerializer(typeof(Xxx));
    using (var  tw = File.CreateText(@"c:\Temp\test.xml"))
    using (var xw = XmlWriter.Create(tw))
    {
        s.SerializeWithStyle(xw, x);    // only line here that needs to change. 
                                        // rest is standard biolerplate.
    }

Код библиотеки, необходимый для этого: (Хранить в том же пространстве имен, поэтому, когда IntelliSense добавляет в пространство имен для атрибута, он также будет использовать методы расширения)

using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Xml.Serialization;
using System.Reflection;
using System.Xml;

namespace NovelTheory.Xml.Serialization
{
    public class XmlStylesheetAttribute : Attribute
    {
        public string Href { get; set; }
        public XmlStylesheetAttribute(string href)
        {
            Href = href;
        }
    }

    public static class XmlStylesheetAttributeExtenstions
    {
        public static void SerializeWithStyle(this XmlSerializer serializer, 
                XmlWriter textWriter, object o)
        {
            AddStyleSheet(textWriter, o);
            serializer.Serialize(textWriter, o);
        }

        public static void SerializeWithStyle(this XmlSerializer serializer, 
                XmlWriter textWriter, object o, XmlSerializerNamespaces namespaces)
        {
            AddStyleSheet(textWriter, o);
            serializer.Serialize(textWriter, o, namespaces);
        }
        private static void AddStyleSheet(XmlWriter textWriter, object o)
        {
            var dnAttribute = o.GetType()
                                            .GetTypeInfo()
                                            .GetCustomAttribute<XmlStylesheetAttribute>();
            if (dnAttribute != null)
                textWriter.WriteProcessingInstruction("xml-stylesheet", 
                                        $@"type=""text/xsl"" href=""{dnAttribute.Href}""");
        }
    }
}
0 голосов
/ 30 января 2016

createXML.WriteProcessingInstruction ("xml-stylesheet", "type = 'text / xsl' href = 'gss.xsl'");

            #region // PAGES
            string pages_xmlurl = Server.MapPath(Url.Content("~/xml/pages_" + lng.code + ".xml")).ToString();
            XmlTextWriter pages_XML = new XmlTextWriter(pages_xmlurl, UTF8Encoding.UTF8);
            pages_XML.WriteStartDocument();
            pages_XML.WriteProcessingInstruction("xml-stylesheet", "type='text/xsl' href='gss.xsl'");
            pages_XML.WriteComment("Generator By OS sitemap generator, http://www.oguzhansari.com");
            pages_XML.WriteStartElement("urlset");
            pages_XML.WriteAttributeString("xmlns", "http://www.sitemaps.org/schemas/sitemap/0.9");
            pages_XML.WriteAttributeString("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance");
            pages_XML.WriteAttributeString("xsi:schemaLocation", "http://www.google.com/schemas/sitemap/0.84");
            pages_XML.WriteEndDocument();
            pages_XML.Close();
            XmlDocument pages_XMLCONTENTS = new XmlDocument();
            pages_XMLCONTENTS.Load(pages_xmlurl);
            var pages = db.pages.Where(w => w.isActive == true & w.isDelete != true).ToList();
            foreach (var pgs in pages)
            {
                XmlElement _element = pages_XMLCONTENTS.CreateElement("url", pages_XMLCONTENTS.DocumentElement.NamespaceURI);
                XmlElement loc = pages_XMLCONTENTS.CreateElement("loc", pages_XMLCONTENTS.DocumentElement.NamespaceURI);
                loc.InnerText = www + Tools.CreateLinkSingleLang("[CORPORATEPAGES]", "[CORPORATEPAGE]", pgs.id, pgs.pages_contents.Where(xw => xw.languageID == lng.id).FirstOrDefault().title, lng.id);
                _element.AppendChild(loc);
                XmlElement lastmod = pages_XMLCONTENTS.CreateElement("lastmod", pages_XMLCONTENTS.DocumentElement.NamespaceURI);
                lastmod.InnerText = DateTime.Now.ToString();
                _element.AppendChild(lastmod);
                XmlElement changefreq = pages_XMLCONTENTS.CreateElement("changefreq", pages_XMLCONTENTS.DocumentElement.NamespaceURI);
                changefreq.InnerText = "daily";
                _element.AppendChild(changefreq);
                XmlElement priority = pages_XMLCONTENTS.CreateElement("priority", pages_XMLCONTENTS.DocumentElement.NamespaceURI);
                priority.InnerText = "0.5";
                _element.AppendChild(priority);
                pages_XMLCONTENTS.DocumentElement.AppendChild(_element);
            }
            XmlTextWriter pages_write = new XmlTextWriter(pages_xmlurl, null);
            pages_write.Formatting = Formatting.Indented;
            pages_XMLCONTENTS.WriteContentTo(pages_write);
            pages_write.Close();
            #endregion
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...