上下文:.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或更好的前向性质。避免将整个文档加载到内存中。
答案 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。
答案 1 :(得分:0)
如果您想避免将整个文档树加载到内存中,您可能需要考虑与XSLT不同的技术。
有一种名为Streaming Transformations for XML (STX)的方法,它不需要构建内存中的树。您可能想查看SourceForge上的STX project。
有关流式转换的概述,我建议使用以下文章:
答案 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文档的任何流式传输。