5

有没有办法调试通过自定义 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,

4

1 回答 1

10
于 2012-08-17T13:49:06.893 回答