可以将XSLT样式表添加到序列化的XML文档中吗?

时间:2009-09-22 16:08:01

标签: c# xml

我有将复杂对象序列化为XML并将其保存为文件的代码,是否有一种在序列化过程中在xml中包含样式表的快捷方法?

使用C#和.net framework v2。

4 个答案:

答案 0 :(得分:30)

您可以使用XmlWriterWriteProcessingInstruction

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

答案 1 :(得分:0)

我写这是为了将问题减少到只在类上添加一个属性,就像我们描述其他所有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}""");
        }
    }
}

答案 2 :(得分:0)

对于那些想知道如何在现代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-negotiation/

答案 3 :(得分:-1)

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