【发布时间】:2011-11-22 23:38:45
【问题描述】:
尝试 xslt 转换时,我在生产环境中遇到间歇性 System.Xml.Xsl.XslTransformException 异常,遗憾的是我无法在开发环境中复制此异常。
异常吐出更多细节:
禁止执行“document()”函数。使用 XsltSettings.EnableDocumentFunction 属性来启用它。一个错误 发生在 C:\path\to\file\CDS.xsl(16,3)。
然而处理代码中的 EnableDocumentFunction 属性是设置为 true:
private void Transform()
{
var keepTrying = true;
var tryCount = 0;
const int maxRetrys = 3;
while (keepTrying)
{
try
{
var xmlResolver = new XmlUrlResolver();
using (var xmlFile = new XmlNodeReader(_xDoc))
{
var settings = new XmlReaderSettings
{
XmlResolver = xmlResolver,
ProhibitDtd = false,
DtdProcessing = DtdProcessing.Ignore
};
using (var xsl = XmlReader.Create(_xslPath, settings))
{
var xslt = new XslCompiledTransform(true);
xslt.Load(xsl, new XsltSettings { EnableDocumentFunction = true }, xmlResolver);
var sb = new StringBuilder();
using (var writer = XmlWriter.Create(sb, xslt.OutputSettings))
{
xslt.Transform(xmlFile, null, writer, xmlResolver); // errors out here.
}
var xhtml = sb.ToString();
_transformedXml = xhtml;
_isTransformed = true;
xsl.Close();
}
}
keepTrying = false;
}
catch (System.Xml.Xsl.XsltException ex)
{
ExceptionPolicy.HandleException(ex, "ExceptionLogging");
tryCount++;
if (tryCount > maxRetrys)
{
keepTrying = false;
throw;
}
}
}
}
xslt 文件由第三方提供并自动更新,因此不可重写。这是它的顶部,出于隐私原因略有修改:
<?xml version="1.0"?>
<!--
Interaction_550.xsl : 20110916
-->
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:example="http://www.example.com" version="1.0">
<xsl:param name="D2DSeverityFilter"></xsl:param>
<xsl:param name="D2HSeverityFilter"></xsl:param>
<xsl:param name="DocumentationFilter"></xsl:param>
<xsl:output method="html"/>
<xsl:key name="d2d_sev_level-lookup" match="example:d2d_sev_level" use="@name"/>
<xsl:key name="d2h_sev_level-lookup" match="example:d2h_sev_level" use="@name"/>
<xsl:key name="d2l_sev_level-lookup" match="example:d2l_sev_level" use="@name"/>
<xsl:key name="preg_cat-lookup" match="example:preg_cat" use="@cat"/>
<xsl:key name="doc_level-lookup" match="example:doc_level" use="@name"/>
<xsl:variable name="d2d_sev_level-top" select="document('')/*/example:d2d_sev_levels"/>
<xsl:variable name="d2h_sev_level-top" select="document('')/*/example:d2h_sev_levels"/>
<xsl:variable name="d2l_sev_level-top" select="document('')/*/example:d2l_sev_levels"/>
<xsl:variable name="doc_level-top" select="document('')/*/example:doc_levels"/>
<xsl:variable name="preg_cat-top" select="document('')/*/example:preg_cats"/>
<xsl:template match="/">
<head>
<style type="text/css">
body {
font-family : arial,sans serif,helvetica;
}
...
我该怎么做:
- 解决这个问题,让它根本不会发生?
- 如果做不到这一点,我该如何在 dev 中复制它?
【问题讨论】:
-
如果样式表在内存中(缓存)或者解析器不知道如何处理空字符串 URL,
document('')函数可能会失败。如果您在生产版本中有缓存,可能就是这种情况。您可以以编程方式将样式表处理为另一个样式表,该样式表不包含document()调用,并且将使用 XslCompiledTransform 成功执行。如果您对这样的解决方案感兴趣,请告诉我,我可以在回复中描述它。 -
谢谢 Dimitre,我将从验证缓存情况开始 - 但如果您能进一步描述处理样式表以删除
document()调用,那就太好了。 -
@_CamM:是的,我发布了一个答案,其中包含执行此所需转换的一般转换。