有没有办法调试通过自定义 XmlUrlResolver 从数据库加载的 XSLT 文档,或者有人知道下面的错误消息是什么吗?
我有一个导入通用 xslt 文档的 XSLT 样式表:
<xsl:import href="db://common.hist.org"/>
该方案由从数据库加载 XSLT 文档的自定义处理XmlResolver
,但出现错误:
已存在具有相同键的条目。
引用的通用 XSLT 文档xsl:import
包含一些通用 XSLT 模板,每个模板都有一个唯一的名称。
将 XSLT 文档从本地文件系统移动到数据库后,开始出现此错误。使用指向本地文件的默认导入方案以及从本地文件系统加载 XSLT 文档时,不会发生错误。
在创建 的实例时,我还尝试打开调试XslCompiledTransform
,但不知何故,无法“进入”基于数据库的 XSLT。
_xslHtmlOutput = new XslCompiledTransform(XSLT_DEBUG);
更新:以下基本上是请求的解析器代码,但我的代码中没有发生异常;因此我猜下面这段代码中没有明显的原因。(同样的代码实际上用于加载包含导入的 XSLT 样式表,并且在注释掉导入时,一切都按预期工作。)
public class XmlDBResolver : XmlUrlResolver
{
private IDictionary<string,string> GetUriComponents(String uri)
{
bool useXmlPre = false;
uri = uri.Replace("db://", "");
useXmlPre = uri.StartsWith("xml/");
uri = uri.Replace("xml/", "");
IDictionary<string, string> dict = new Dictionary<string, string>();
string app = null, area = null, subArea = null;
if (!String.IsNullOrWhiteSpace(uri))
{
string[] components = uri.Split('.');
if (components == null)
throw new Exception("Invalid Xslt URI");
switch (components.Count())
{
case 3:
app = components[0];
break;
case 4:
area = components[0];
app = components[1];
break;
case 5:
subArea = components[0];
area = components[1];
app = components[2];
break;
default:
throw new Exception("Invalid Xslt URI");
}
dict.Add("application", app);
dict.Add("area", area);
dict.Add("subArea", subArea);
dict.Add("xmlPreTransform", String.Format("{0}", useXmlPre));
}
return dict;
}
public override System.Net.ICredentials Credentials
{
set { /* TODO: check if we need credentials */ }
}
public override object GetEntity(Uri absoluteUri, string role, Type ofObjectToReturn)
{
/*
* db://<app>.hist.org
* db://<area>.<app>.hist.org
* db://<subArea>.<area>.<app>.hist.org
*
* */
Tracing.TraceHelper.WriteLine(String.Format("GetEntity {0}", absoluteUri));
XmlReader reader = null;
switch (absoluteUri.Scheme)
{
case "db":
string origString = absoluteUri.OriginalString;
IDictionary<string, string> xsltDict = GetUriComponents(origString);
if(String.IsNullOrWhiteSpace(xsltDict["area"]))
{
reader = DatabaseServiceFactory.DatabaseService.GetApplicationXslt(xsltDict["application"]);
}
else if (!String.IsNullOrWhiteSpace(xsltDict["area"]) && String.IsNullOrWhiteSpace(xsltDict["subArea"]) && !Boolean.Parse(xsltDict["xmlPreTransform"]))
{
reader = DatabaseServiceFactory.DatabaseService.GetAreaXslt(xsltDict["application"], xsltDict["area"]);
}
else if (!String.IsNullOrWhiteSpace(xsltDict["area"]) && !String.IsNullOrWhiteSpace(xsltDict["subArea"]))
{
if(Boolean.Parse(xsltDict["xmlPreTransform"]))
reader = DatabaseServiceFactory.DatabaseService.GetSubareaXmlPreTransformXslt(xsltDict["application"], xsltDict["area"], xsltDict["subArea"]);
else
reader = DatabaseServiceFactory.DatabaseService.GetSubareaXslt(xsltDict["application"], xsltDict["area"], xsltDict["subArea"]);
}
return reader;
default:
return base.GetEntity(absoluteUri, role, ofObjectToReturn);
}
}
为了完整性,IDatabaseService 接口(相关部分):
public interface IDatabaseService
{
...
XmlReader GetApplicationXslt(String applicationName);
XmlReader GetAreaXslt(String applicationName, String areaName);
XmlReader GetSubareaXslt(String applicationName, String areaName, String subAreaName);
XmlReader GetSubareaXmlPreTransformXslt(String applicationName, String areaName, String subAreaName);
}
更新:我试图通过临时从 Web 服务器加载样式表来隔离问题,这很有效。我了解到,与存储在 Web 服务器上的样式表相比,SQL Server 显然只存储没有 XML 声明的 XML 片段。
更新:异常的堆栈跟踪:
System.Xml.Xsl.XslLoadException:XSLT-Kompilierungsfehler。费勒贝 (9,1616)。---> System.ArgumentException: 已存在具有相同键的条目.. bei System.Collections.Specialized.ListDictionary.Add(Object key, Object value) bei System.Collections.Specialized.HybridDictionary.Add(Object key, Object value) bei System.Xml.Xsl.Xslt.XsltLoader.LoadStylesheet(XmlReader reader, Boolean include) bei System.Xml.Xsl.Xslt.XsltLoader.LoadStylesheet(Uri uri, Boolean include) bei System.Xml.Xsl.Xslt.XsltLoader .LoadStylesheet(XmlReader reader, Boolean include) --- Ende der inneren Ablaufverfolgung des Ausnahmestacks --- bei System.Xml.Xsl.Xslt.XsltLoader.LoadStylesheet(XmlReader reader, Boolean include) bei System.Xml.Xsl.Xslt.XsltLoader .Load(XmlReader reader) bei System.Xml.Xsl.Xslt.XsltLoader.Load(Compiler compiler, Object stylesheet,