C# 例外情况;样式表太复杂了”;在.NET 4.5中加载大型XSLT时
尝试加载XSLT样式表时出现异常。XSLT样式表非常大(几乎8000行)。不幸的是,我无法控制这一点,我无法重构样式表使其更小 我们最近升级到了.Net Framework 4.5。下面的命令在升级之前运行良好(我们使用的是.Net Framework 4.0)。升级后,我们收到一个C# 例外情况;样式表太复杂了”;在.NET 4.5中加载大型XSLT时,c#,xslt,.net-4.5,C#,Xslt,.net 4.5,尝试加载XSLT样式表时出现异常。XSLT样式表非常大(几乎8000行)。不幸的是,我无法控制这一点,我无法重构样式表使其更小 我们最近升级到了.Net Framework 4.5。下面的命令在升级之前运行良好(我们使用的是.Net Framework 4.0)。升级后,我们收到一个XsltException,在transform.Load行上显示“样式表太复杂” 我希望有一些新的设置会说“让这个命令像4.0中那样工作”,但我在任何地方都找不到任何东西 有人知道为什么4.5版本会突然出现问题吗?
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。结果表明这是.Net Framework 4.5中的一个特性/缺陷。来自Microsoft的消息
我们最近在热修复汇总中发布了一个修复程序。有关.NET Framework 4.0和.NET Framework 4.5,请参见
然后将其添加到配置文件中,问题就会消失
<?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>
这解决了我的问题。我也遇到了同样的问题,并将其隔离到一个机器生成的choice元素中,该元素包含1500多个xsl:when元素。进一步的测试证明.NET4.7将在789中给出“太复杂”的异常,当元素或更多元素出现时 在app.config中将limitXPathComplexity设置为false会导致程序崩溃,而使用StackOverflowException
NET Core 2.0上的相同代码在APPX2800元素处抛出StackOverflowException。我已经向这两个团队报告了这个bug,但不希望它很快得到优先处理。我解决了这个问题,将用于键/值映射的数千条xsl:choose和xsl:if语句替换为外部xml文件键/值查找 剽窃的方法在这里-学分如下 就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:choose。当然,document函数不必加载静态文件,它可以向提供XML的HTTP服务器发出GET请求
学分:
@RyanGates现在读起来好多了。感谢您的编辑。请务必在问题标题中使用主题关键字,如果它们对澄清主题很重要(即使它们碰巧也是标记)。对于@Ryan linked to这个问题的唯一答案实际上是建议在标题中使用主题关键字(也是标记),比如“我可以使用jQuery来…”这个词的样式表很模糊,因此在标题中使用XSLT来限定它是值得的。我错了。我个人认为,如果你看标签的话,标题不会模棱两可。话虽如此,在更仔细地阅读链接后,我可以理解您关于有机和强制之间区别的意思。您好,我来自.NET Framework兼容性团队。我们希望更好地理解这一点。你能通过微软网站netfx45compat与我们联系吗?我们有一个小项目来重现这个问题?@Sprague,这是正确的。出于某种原因,Microsoft要求您与他们联系以获取修补程序。但是每个KB页面上都有一个链接,提供了联系微软的方式。我不喜欢这个,我一点也不喜欢。当我从他们那里得到我想要的东西的时候,我将以艰难的方式进行调试(我实际上就是这样做的…)有趣的是,当我联系他们的时候,我就在同一天得到了修补程序。我从未声称试图联系他们。不管怎样,这并不重要。至少,知识库本可以更切中要害。下载链接会非常好。实际上,这只会将问题从解析/编译XSLT转移到执行XSLT。这似乎是MS内置的防止堆栈溢出的安全功能。停用它会导致3000个字符XSLT的堆栈溢出。正如您所知,SOs无法被捕获并将终止该过程,因此这是相当危险的!我们通过为频繁使用的节点集引入变量来重构XSLT,但最终不得不启动一个定制的工作线程池,增加堆栈大小来处理XSLT。这似乎是MS内置的防止堆栈溢出的安全功能。我们通过为经常使用的节点集引入变量来重构XSLT,但最终不得不启动一个堆栈大小增加为2MB的自定义工作线程池来处理XSLT,特别是在IIS上,32/64位进程的堆栈大小仅为256/512kB。到目前为止,这是可行的。