如何在C#中应用XSLT样式表

201

我想用C#将XSLT样式表应用到XML文档,并将输出写入文件。


11
实际上,我认为这是一个很好的问题,而且你提供了一个不错的答案。提名重新开放。 - Dominic Rodger
我发现Xslt很困惑,所以这个链接对我很有帮助:https://github.com/beto-rodriguez/SuperXml - bto.rdz
5个回答

185

我在这里找到了一个可能的答案:http://web.archive.org/web/20130329123237/http://www.csharpfriends.com/Articles/getArticle.aspx?articleID=63

文章内容如下:

XPathDocument myXPathDoc = new XPathDocument(myXmlFile) ;
XslTransform myXslTrans = new XslTransform() ;
myXslTrans.Load(myStyleSheet);
XmlTextWriter myWriter = new XmlTextWriter("result.html",null) ;
myXslTrans.Transform(myXPathDoc,null,myWriter) ;

编辑:

但是我的可靠编译器指出,XslTransform 已过时:请使用 XslCompiledTransform 替代:

XPathDocument myXPathDoc = new XPathDocument(myXmlFile) ;
XslCompiledTransform myXslTrans = new XslCompiledTransform();
myXslTrans.Load(myStyleSheet);
XmlTextWriter myWriter = new XmlTextWriter("result.html",null);
myXslTrans.Transform(myXPathDoc,null,myWriter);

自从我采用了你的一些答案来创建我要链接的类,我想把它作为评论放在这里。希望这能让人们更简单地理解: http://dftr.ca/?p=318 - DFTR
我更喜欢这个解决方案而不是过载版本,因为你可以使用DTD、Schemas等设置XmlReaderSettingsXmlWriterSettings - Alina B.
2
我需要在VB.NET中完成这个任务(这是我的“备用”语言,我更喜欢C#),你的答案帮助我解决了问题。谢谢。 - Eon

146

根据 Daren 的优秀回答,注意使用适当的 XslCompiledTransform.Transform overload 可以大大缩短代码:

var myXslTrans = new XslCompiledTransform(); 
myXslTrans.Load("stylesheet.xsl"); 
myXslTrans.Transform("source.xml", "result.html"); 

(很抱歉以回答的形式发表此问题,但是在评论中支持代码块的功能非常有限。)

在VB.NET中,您甚至不需要一个变量:

With New XslCompiledTransform()
    .Load("stylesheet.xsl")
    .Transform("source.xml", "result.html")
End With

15

7
这是一个仅包含链接的回答。请包括链接页面的相关部分。 - Thomas Weller
两个链接已经失效。 - Adrian S

4

这可能会对您有所帮助。

public static string TransformDocument(string doc, string stylesheetPath)
{
    Func<string,XmlDocument> GetXmlDocument = (xmlContent) =>
     {
         XmlDocument xmlDocument = new XmlDocument();
         xmlDocument.LoadXml(xmlContent);
         return xmlDocument;
     };

    try
    {
        var document = GetXmlDocument(doc);
        var style = GetXmlDocument(File.ReadAllText(stylesheetPath));

        System.Xml.Xsl.XslCompiledTransform transform = new System.Xml.Xsl.XslCompiledTransform();
        transform.Load(style); // compiled stylesheet
        System.IO.StringWriter writer = new System.IO.StringWriter();
        XmlReader xmlReadB = new XmlTextReader(new StringReader(document.DocumentElement.OuterXml));
        transform.Transform(xmlReadB, null, writer);
        return writer.ToString();
    }
    catch (Exception ex)
    {
        throw ex;
    }

}   

文档和document.DocumentElement.OuterXml有什么区别? - sasjaq
doc 被定义为 string 类型的参数,该参数被传递给 Func<string,XmlDocument> GetXmlDocument 函数,该函数加载并返回 XmlDocument 类型。document.DocumentElementXmlElement 类型的属性,而 OuterXmlXmlElement 的字符串属性,用于获取字符串。参考 [https://learn.microsoft.com/en-us/dotnet/api/system.xml.xmldocument.documentelement?view=net-6.0]。 - Vinod Srivastav
正确答案是没有区别...它们都是完全相同的值...因此,您不需要将文档反序列化为XmlDocument,并提取具有OuterXml的相同xml... - sasjaq
@sasjaq 正确答案是:Transform 方法被重载了15种不同的形式,你可以使用其中任何一种。是的,它也可以被称为 Transform(string,string),但这并不意味着它就是正确的。xslt 被起草了,但 xml 才是业务数据,Func 确保数据是正确的 xml,然后才能继续进行。我在那里放了一个记录器来记录这个过程。请参考 [https://docs.microsoft.com/en-us/dotnet/api/system.xml.xsl.xslcompiledtransform.transform?view=net-6.0#System_Xml_Xsl_XslCompiledTransform_Transform_System_Xml_XPath_IXPathNavigable_System_Xml_XmlWriter_] 的 Transform - Vinod Srivastav

0

我想分享这个小代码片段,它从数据库中读取数据并使用XSLT进行转换。在顶部,我还使用了xslt-extensions,使其与其他代码略有不同。

注意:这只是一个草稿代码,在生产环境中使用前可能需要进行清理。

var schema = XDocument.Load(XsltPath);
using (var connection = new SqlConnection(ConnectionString))
{
    connection.Open();
    using (var command = new SqlCommand(Sql, connection))
    {
        var reader = command.ExecuteReader();
        var dt = new DataTable(SourceNode);
        dt.Load(reader);
                    
        string xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + Environment.NewLine;
        using (var stringWriter = new StringWriter())
        {
            dt.WriteXml(stringWriter, true);
            xml += stringWriter.GetStringBuilder().ToString();
        }

        XDocument transformedXml = new XDocument();
        var xsltArgumentList = new XsltArgumentList();
        xsltArgumentList.AddExtensionObject("urn:xslt-extensions", new XsltExtensions());

        using (XmlWriter writer = transformedXml.CreateWriter())
        {
            XslCompiledTransform xslt = new XslCompiledTransform();
            xslt.Load(schema.CreateReader());
            xslt.Transform(XmlReader.Create(new StringReader(xml)), xsltArgumentList, writer);
        }
        var result = transformedXml.ToString();
    }
}

XsltPath 是指向你的 XSLT 文件的路径。
ConnectionString 常量指向你的数据库。
Sql 是你的查询语句。
SourceNode 是源 XML 中每个记录的节点。

现在是有趣的部分,请注意上述代码中使用了 urn:xslt-extensionsnew XsltExtensions()。如果需要进行一些 XSLT 无法完成的复杂计算,可以使用这个方法。以下是一个格式化日期的简单方法。

public class XsltExtensions
{
    public string FormatDate(string dateString, string format)
    {
        DateTime date;

        if (DateTime.TryParse(dateString, out date))
            return date.ToString(format);

        return dateString;
    }
}

在XSLT文件中,您可以按如下方式使用它;
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:ext="urn:xslt-extensions">
...
<myTag><xsl:value-of select="ext:FormatDate(record_date, 'yyyy-MM-dd')"/></myTag>
...
</xsl:stylesheet>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接