C#如何在内存中对一个对象执行实时XSLT转换?

8

我有一个函数,需要传入两个参数:1 = XML文件,2 = XSLT文件,然后执行转换并返回生成的HTML。

下面是这个函数:

/// <summary>
/// Will apply an XSLT style to any XML file and return the rendered HTML.
/// </summary>
/// <param name="xmlFileName">
/// The file name of the XML document.
/// </param>
/// <param name="xslFileName">
/// The file name of the XSL document.
/// </param>
/// <returns>
/// The rendered HTML.
/// </returns>
public string TransformXml(string xmlFileName, string xslFileName)
{
    var xtr = new XmlTextReader(xmlFileName)
                  {
                      WhitespaceHandling = WhitespaceHandling.None
                  };
    var xd = new XmlDocument();
    xd.Load(xtr);

    var xslt = new System.Xml.Xsl.XslCompiledTransform();
    xslt.Load(xslFileName);
    var stm = new MemoryStream();
    xslt.Transform(xd, null, stm);
    stm.Position = 1;
    var sr = new StreamReader(stm);
    xtr.Close();
    return sr.ReadToEnd();
}

我希望更改该函数的功能,使其不再接受XML文件,而是仅接受一个对象作为输入。 如果将对象序列化为文件,则该对象与XSLT完全兼容。但我不想先将其序列化到文件中。
因此,简要概括一下:保留来自文件的XSLT,但XML输入应该是我传递的对象,并且希望能够生成XML,而无需进行任何文件系统交互。
4个回答

9
您可以将对象序列化为字符串,将字符串加载到XmlDocument中,并执行转换:
public string TransformXml(object data, string xslFileName)
{

    XmlSerializer xs = new XmlSerializer(data.GetType());
    string xmlString;
    using (StringWriter swr = new StringWriter())
    {
        xs.Serialize(swr, data);
        xmlString = swr.ToString();
    }

    var xd = new XmlDocument();
    xd.LoadXml(xmlString);

    var xslt = new System.Xml.Xsl.XslCompiledTransform();
    xslt.Load(xslFileName);
    var stm = new MemoryStream();
    xslt.Transform(xd, null, stm);
    stm.Position = 0;
    var sr = new StreamReader(stm);
    return sr.ReadToEnd();
}

1
我刚使用了这个,但必须指出我需要将Position更改为= 0。否则它按预期工作。=) - Dracorat

3
这里有一个函数,可以将一个对象转换为XDocument(如果你还没有使用XDocument,则可以更改为XmlDocument)。当然,如果对象不可序列化,这将会抛出异常。
public static XDocument ConvertToXml<T>(this T o)
{
    StringBuilder builder = new StringBuilder();
    StringWriter writer = new StringWriter(builder);
    XmlSerializer serializer = new XmlSerializer(typeof(T));
    serializer.Serialize(writer,o);
    StringReader reader = new StringReader(builder.ToString());
    return XDocument.Load(reader);
}

这里是XmlDocument的翻译。

public static XmlDocument ConvertToXml<T>(this T o)
{
    StringBuilder builder = new StringBuilder();
    StringWriter writer = new StringWriter(builder);
    XmlSerializer serializer = new XmlSerializer(typeof(T));
    serializer.Serialize(writer,o);
    StringReader reader = new StringReader(builder.ToString());
    XmlDocument doc = new XmlDocument();
    doc.Load(reader);
    return doc;
}

XslCompiledTransform 需要一个 XmlDocument,而不是 XDocument... 否则,这大致与我的想法相同 ;) - Thomas Levesque

1

尚未测试,但您可以使用XPathDocument来获取流,由于XPathDocument实现了IXPathNavigable,因此它可用于转换:

 public string TransformXml(Stream xmlFile, string xslFileName) 
 { 
      var doc = new XPathDocument(xmlFile);
      var xslt = new System.Xml.Xsl.XslCompiledTransform(); 
      xslt.Load(xslFileName); 
      var stm = new MemoryStream(); 
      xslt.Transform(doc, null, stm); 
      stm.Position = 1; 
      var sr = new StreamReader(stm); 
      return sr.ReadToEnd(); 
  } 

0

看一下这篇文章,它描述了创建一个XPathNavigator,可以浏览对象图的属性,这是XPath和XSLT的一个非常强大的组合。


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