C# 是否可以将XSLT样式表添加到序列化的XML文档?
我有将复杂对象序列化为XML并将其保存为文件的代码,在序列化过程中有没有一种快速的方法在XML中包含样式表 使用C#和.net framework v2.可以使用和:C# 是否可以将XSLT样式表添加到序列化的XML文档?,c#,xml,C#,Xml,我有将复杂对象序列化为XML并将其保存为文件的代码,在序列化过程中有没有一种快速的方法在XML中包含样式表 使用C#和.net framework v2.可以使用和: createXML.WriteProcessingInstruction(“xml样式表”,“type='text/xsl'href='gss.xsl'”) 我写这篇文章是为了将问题简化为只在类上添加一个属性,就像我们描述其他所有xml构造指令一样: 用途如下: [XmlStylesheet("USED-FILE.xsl"
createXML.WriteProcessingInstruction(“xml样式表”,“type='text/xsl'href='gss.xsl'”)
我写这篇文章是为了将问题简化为只在类上添加一个属性,就像我们描述其他所有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为属性添加名称空间时,它也将引入扩展方法)
使用系统;
使用System.Collections.Generic;
使用System.IO;
使用系统文本;
使用System.Xml.Serialization;
运用系统反思;
使用System.Xml;
命名空间NovelTheory.Xml.Serialization
{
公共类XmlStylesheetAttribute:属性
{
公共字符串Href{get;set;}
公共XmlStylesheetAttribute(字符串href)
{
Href=Href;
}
}
公共静态类XmlStyleSheetAttributeExtensions
{
公共静态void SerializeWithStyle(此XmlSerializer序列化程序,
XmlWriter textWriter,对象o)
{
添加样式表(textWriter,o);
serializer.Serialize(textWriter,o);
}
公共静态void SerializeWithStyle(此XmlSerializer序列化程序,
XmlWriter textWriter、对象o、XmlSerializerNamespaces(命名空间)
{
添加样式表(textWriter,o);
序列化(textWriter、o、名称空间);
}
私有静态void AddStyleSheet(XmlWriter textWriter,对象o)
{
var dnAttribute=o.GetType()
.GetTypeInfo()
.GetCustomAttribute();
if(dnAttribute!=null)
textWriter.WriteProcessingInstruction(“xml样式表”,
$@“type=”“text/xsl”“href=”“{dnAttribute.href}”“”;
}
}
}
对于那些想知道如何在现代dotnet core中实现类似功能的人,您需要做一些调整:
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"
}
};
}
}
和XML:
curl -k -i -s -H 'Accept: text/xml' http://localhost:5000/posts
这里可以找到用于演示的xsl示例:在我的解决方案中,它将所有内容都写在一行上。我可以调整在多行上写它吗?对于懒惰的人,
XmlSerializer
位于System.Xml.Serialization
命名空间中。这只是重复了部分现有的向上投票的答案。
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}""");
}
}
}
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"
}
};
}
}
curl -k -i -s -H 'Accept: application/json' http://localhost:5000/posts
curl -k -i -s -H 'Accept: text/xml' http://localhost:5000/posts