如何在.NET中链接/嵌套XSL转换

时间:2010-09-16 14:14:29

标签: .net xml .net-3.5 xslt

上下文:.NET Framework 3.5

我意识到如何使用XSLT执行单个XML转换,但没有找到关于链接XML转换的任何好例子。

输入: - XML文档作为XPathDocument。 - 文件到多个XSL文件的路径。

预期产量: - 最好是XPathDocument / IXPathNavigable,逐个表示应用了所有转换的XML。

示例方案

输入xml:<doc></doc>

xsl-1:.xsl,它将<one />添加为doc元素的子元素。 xsl-2:.xsl,它将<two />添加为doc元素的子元素。

预期结果

<doc><one /><two /></doc>

目标

利用XPathDocument / IXPathNavigable或更好的前向性质。避免将整个文档加载到内存中。

3 个答案:

答案 0 :(得分:2)

也许类似以下内容(我还没有尝试编译):

XslCompiledTransform xsl1 = new XslCompiledTransform();
xsl1.Load("xsl1.xsl");

XslCompiledTransform xsl2 = new XslCompiledTransform();
xsl1.Load("xsl2.xsl");

using (Stream stream = new MemoryStream())
{
     using (XmlReader xmlReader1 = XmlReader.Create("source.xml"))
     {
          xsl1.Transform(xmlReader1, stream);
     }

     stream1.Position = 0;

     using (XmlReader xmlReader2 = XmlReader.Create(stream))
     {
         xsl2.Transform(xmlReader2, "output.xml");
     }
}

通过使用xmlreader,您将获得前进,只有您正在寻找。我刚刚将第一个结果输出到MemoryStream,但你可以将它做到临时文件。

为了获得额外的一点性能,您可能需要预先编译xslt。

XSLT Compiler (xsltc.exe)

答案 1 :(得分:0)

如果您想避免将整个文档树加载到内存中,您可能需要考虑与XSLT不同的技术。

有一种名为Streaming Transformations for XML (STX)的方法,它不需要构建内存中的树。您可能想查看SourceForge上的STX project

有关流式转换的概述,我建议使用以下文章:

  

<强> An Introduction to Streaming Transformations for XML

答案 2 :(得分:0)

<强>予。这演示了如何使用支持exslt node-set()扩展函数的任何XSLT 1.0处理器执行多次传递XSLT 1.0转换,包括.NET XslCompiledTransform。

对于其他XSLT 1.0处理器,需要用它们支持的任何内容替换ext:node-set(),例如msxsl:node-set()(与正确名称空间相关联的msxsl)用于MSXML。

<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:ext="http://exslt.org/common"
    exclude-result-prefixes="ext xsl">
    <xsl:output omit-xml-declaration="yes" indent="yes"/>

 <xsl:template match="node()|@*" name="identity">
     <xsl:copy>
       <xsl:apply-templates select="node()|@*"/>
     </xsl:copy>
 </xsl:template>

 <xsl:template match="/">
  <xsl:variable name="vrtfPass1">
   <xsl:apply-templates select="node()"/>
  </xsl:variable>

  <xsl:apply-templates mode="pass2"
   select="ext:node-set($vrtfPass1)/node()"/>
 </xsl:template>

 <xsl:template match="/*">
     <xsl:copy>
       <xsl:copy-of select="@*"/>
       <one/>
     <xsl:apply-templates/>
     </xsl:copy>
 </xsl:template>

 <xsl:template match="node()|@*" mode="pass2">
     <xsl:copy>
       <xsl:apply-templates select="node()|@*" mode="pass2"/>
     </xsl:copy>
 </xsl:template>

 <xsl:template match="/*/one" mode="pass2" >
     <xsl:call-template name="identity"/>
      <two/>
 </xsl:template>
</xsl:stylesheet>

在此XML文档上应用此转换时

<doc/>

生成了想要的结果

<doc>
   <one/>
   <two/>
</doc>

II。 目前XSLT 1.0和XSLT 2.0使用XPath,这需要整个XML文档(表示)在RAM

Working Draft for XSLT 2.1 (最近更名为3.0)提出了一个新的 streaming feature ,如果此WD成为官方推荐,则会使兼容的XSLT 3.0处理器能够实现流式传输。

<强> III。 XPathDocument的XslCompiledTransform仍然将整个XML文档表示保存在内存中。 XPathDocument提供仅向前迭代的事实并不意味着XslCompiledTransform执行XML文档的任何流式传输。