Есть ли способ отлаживать документы XSLT, которые загружаются из базы данных с помощью пользовательского XmlUrlResolver, или кто-нибудь знает, о чем сообщение об ошибке ниже?
У меня есть таблица стилей XSLT, которая импортирует общий документ xslt :
. Схема обрабатывается пользовательскимXmlResolver
который загружает документ XSLT из БД, но я получаю сообщение об ошибке:
An entry with the same key already exists.
Общий документ XSLT, на который ссылается xsl:import
, содержит несколько общих шаблонов XSLT, каждый из которых имеет уникальное имя.
Эта ошибка начала возникать после перемещения XSLT-документов из локальной файловой системы в базу данных. При использовании схем импорта по умолчанию, указывающих на локальные файлы, и при загрузке документов XSLT из локальной файловой системы ошибка не возникает.
Я также пытался включить отладку при создании экземпляра XslCompiledTransform
, но почему-то невозможно «зайти» в базу данных -на основе XSLT.
_xslHtmlOutput = new XslCompiledTransform(XSLT_DEBUG);
Обновление:Ниже приведен в основном код преобразователя, как запрошено, но исключение не происходит внутри моего кода; таким образом, я не думаю, что в приведенном ниже коде нет очевидной причины. (Этот же код фактически используется для загрузки таблиц стилей XSLT, содержащих импорт, и при комментировании импорта все работает как положено.)
public class XmlDBResolver : XmlUrlResolver
{
private IDictionary GetUriComponents(String uri)
{
bool useXmlPre = false;
uri = uri.Replace("db://", "");
useXmlPre = uri.StartsWith("xml/");
uri = uri.Replace("xml/", "");
IDictionary dict = new Dictionary();
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://.hist.org
* db://..hist.org
* db://...hist.org
*
* */
Tracing.TraceHelper.WriteLine(String.Format("GetEntity {0}", absoluteUri));
XmlReader reader = null;
switch (absoluteUri.Scheme)
{
case "db":
string origString = absoluteUri.OriginalString;
IDictionary 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);
}
Обновление:Я попытался изолировать проблему, временно загрузив таблицы стилей с веб-сервера, и это работает. Я узнал, что SQL Server, по-видимому, хранит только фрагменты XML без объявления XML, в отличие от таблиц стилей, хранящихся на веб-сервере.
Обновление:Трассировка стека исключения:
System.Xml.Xsl.XslLoadException: XSLT-Kompilierungsfehler. Fehler bei (9,1616). ---> System.ArgumentException: An entry with the same key already exists.. 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, XmlResolver xmlResolver) bei System.Xml.Xsl.Xslt.Compiler.Compile(Object stylesheet, XmlResolver xmlResolver, QilExpression& qil) bei System.Xml.Xsl.XslCompiledTransform.LoadInternal(Object stylesheet, XsltSettings settings, XmlResolver stylesheetResolver) bei System.Xml.Xsl.XslCompiledTransform.Load(String stylesheetUri, XsltSettings settings, XmlResolver stylesheetResolver) bei (my namespace and class).GetXslTransform(Boolean preTransform) bei (my namespace and class).get_XslHtmlOutput() bei (my namespace and class).get_DisplayMarkup()