尝试加载XSLT样式表时出现异常。 XSLT样式表非常大(近8,000行)。不幸的是,我对此没有任何控制权,而且我无法重构样式表以使其变小。
我们最近升级到.Net Framework 4.5。以下命令在升级之前工作得很好(我们使用的是.Net Framework 4.0)。升级后,我们会在XsltException
行收到transform.Load
,上面写着“样式表过于复杂”。
我希望有一些新的设置可以说“让这个命令按照它在4.0中的方式工作”,但我找不到任何地方。
有人知道为什么这可能在4.5版本中突然出现问题?怎么解决?
XslCompiledTransform transform = new XslCompiledTransform();
transform.Load(XmlReader.Create(report), new XsltSettings { EnableScript = true }, new XmlUrlResolver());
report
是一个包含大型XSLT样式表的MemoryStream。
答案 0 :(得分:8)
原来这是.Net Framework 4.5中的一个功能/缺陷。来自Microsoft的消息...
我们最近在修补程序汇总中发布了此修复程序。有关.NET Framework 4.0,请参阅http://support.microsoft.com/kb/2828843,对于.NET Framework 4.5,请参阅http://support.microsoft.com/kb/2828841。
然后将其添加到您的配置文件中,问题应该消失。
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<sectionGroup name="system.xml">
<section name="xslt" type="System.Xml.XmlConfiguration.XsltConfigSection, System.Xml, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false"/>
</sectionGroup>
</configSections>
<system.xml>
<xslt limitXPathComplexity="false"/>
</system.xml>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5"/>
</startup>
</configuration>
这解决了我的问题。
答案 1 :(得分:2)
我有同样的问题,并将其隔离到机器生成的选择元素,其中包含超过1500 xsl:when-elements。进一步的测试证明.NET 4.7将在789或更多元素时给出“太复杂”的异常。
在app.config中将limitXPathComplexity设置为false会导致程序使用StackOverflowException崩溃。
.NET Core 2.0上的相同代码会在appx 2800元素处抛出StackOverflowException。我已经向两个团队报告了这个错误,但是不要指望它很快会被优先考虑。
答案 2 :(得分:0)
通过使用外部xml文件键/值查找替换成千上万的xsl:choose和xsl:if语句用于键/值映射,我解决了这个问题。
这里有抄袭方法 - 以下信用。
就XSLT而言,最好的方法是将查找数据作为XML文档,然后使用XSLT文档函数加载。例如,如果您以例如
的形式获得查找XML<list>
<data key="k1" value="value 1"/>
<data key="k2" value="value 2"/>
<data key="k3" value="value 3"/>
</list>
然后使用XSLT,你可以做到。
<xsl:variable name="data" select="document('lookup.xml')/list/data"/>
<xsl:for-each select="foo">
<xsl:value-of select="$data[@key = current()]/@value"/>
</xsl:for-each>
无需xsl:选择。当然,文档函数不必加载静态文件,它可以向提供XML的HTTP服务器发出GET请求。