Как разрешить элементы <xsl: import> и <xsl: include> с относительными путями при использовании xsltc.exe XslCompiledTransforms? - PullRequest
5 голосов
/ 24 января 2012

В рамках процесса сборки нашего веб-приложения я настроил наши таблицы стилей XSLT для сборки с помощью компилятора Microsoft xsltc.exe всякий раз, когда мы запускаем полную компиляцию.Во время локальной разработки это работало отлично, так как код компилируется и размещается в одном месте.Однако, как только это было установлено на сервере сборки, возникли проблемы.

Сервер сборки будет компилировать таблицы стилей XSLT, как я это делаю локально, но затем запускается скрипт, который развертывает скомпилированный код на нашем внутреннем промежуточном веб-сервере.,После того, как эти двоичные файлы переместились из того места, где они были скомпилированы, относительные пути в элементах <xsl:import> и <xsl:include> перестают корректно разрешаться, что приводит к возникновению исключений, которые выглядят следующим образом при запуске таблиц стилей XSLT.

Could not find a part of the path 'e:\{PATH}\xslt\docbook\VERSION'.
    at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
    at System.IO.FileStream.Init(String path, FileMode mode, FileAccess access, Int32 rights, Boolean useRights, FileShare share, Int32 bufferSize, FileOptions options, SECURITY_ATTRIBUTES secAttrs, String msgPath, Boolean bFromProxy, Boolean useLongPath)
    at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share, Int32 bufferSize, FileOptions options, String msgPath, Boolean bFromProxy)
    at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share, Int32 bufferSize)
    at System.Xml.XmlUrlResolver.GetEntity(Uri absoluteUri, String role, Type ofObjectToReturn)
    at System.Xml.Xsl.Runtime.XmlQueryContext.GetDataSource(String uriRelative, String uriBase)

Вот общее представление о коде в его нынешнем виде:

var xslt = new XslCompiledTransform();
xslt.Load(typeof(Namespace.XslTransforms.CompiledXsltStylesheet));
xslt.Transform("input.xml", "output.xml");

Сейчас я использую метод XslCompiledTransform.Load () с единственным параметром «Тип» для ввода в xsltc.exe на основепредварительно скомпилированные таблицы стилей XSLT.По трассировке стека я могу сказать, что .NET Framework использует XmlUrlResolver, чтобы попытаться определить фактическое расположение этих внешних таблиц стилей, но я не вижу способа обеспечить переопределенную реализацию XmlResolver, где я мог бы передать новыйbaseUri, который указывает, где эти таблицы стилей находятся на веб-сервере.

Я полагаю, что могу решить эту проблему, прекратив предварительную компиляцию с xsltc.exe и загрузив таблицы стилей XSLT через XmlReaders, так как это позволит мне использовать другие методы XslCompiledTransform.Load () , в которых есть параметр, в котором я могу предоставить свою собственную реализацию XmlResolver.Тем не менее, мне нравится опция предварительной компиляции для проверки синтаксиса и производительности, поэтому я не хочу отказываться от нее, если мне это абсолютно не нужно.

Есть ли способ использовать xsltc.exe дляпредварительно скомпилировать эти таблицы стилей XSLT, но при этом предоставить способ явного указания baseUri для относительного разрешения пути элементов <xsl:include> и <xsl:import> во время выполнения?

Ответы [ 3 ]

3 голосов
/ 04 апреля 2012

После лота игры с этим я обнаружил, что был прав, что предоставленный мною код автоматически использует System.Xml.XmlUrlResolver для разрешения <xsl:include>и <xsl:import> относительные пути во время выполнения.Однако использование XmlUrlResolver не привязано к System.Xml.XslCompiledTransform , когда он помещается в двоичный файл с помощью xsltc.exe. XmlResolver фактически выбирается свойством XmlResolver в System.Xml.XmlReaderSettings в System.Xml.XmlReader , который выполняет преобразование при запуске-time. Как только я установил свой собственный пользовательский XmlResolver на используемые мной XsltReaderSettings, я смог контролировать относительное разрешение пути.

Если вы хотите переопределить этот XmlResolver, как я сделал, следующий код можетбыть использованным в качестве руководства:

var customXmlResolver = new SomeCustomXmlResolver();  // Derives from XmlResolver
var xmlReaderSettings = new XmlReaderSettings {
  XmlResolver = customXmlResolver
};

var xslt = new XslCompiledTransform();
xslt.Load(typeof(Namespace.XslTransforms.CompiledXsltStylesheet));

using (var xmlReader = XmlReader.Create("input.xml", xmlReaderSettings)) {
  using (var xmlWriter = XmlWriter.Create("output.xml")) {
    xslt.Transform(xmlReader, null, xmlWriter, customXmlResolver);
  }
}

Я все еще использую xsltc.exe для компиляции своих таблиц стилей XSLT, но когда я загружаю эти скомпилированные таблицы стилей на веб-сервер, введенные SomeCustomXmlResolver перезаписывают пути переопределеннымиМетоды ResolveUri() и GetEntity(), позволяющие находить ссылочные файлы, которые находятся в относительных путях на основе <xsl:include> и <xsl:import>.В качестве дополнительного бонуса, добавив тот же XmlResolver в конец метода Transform(), операции document() в XML также будут корректно разрешать их относительные пути.

2 голосов
/ 25 января 2012

Есть ли способ использовать xsltc.exe для предварительной компиляции этих таблиц стилей XSLT, тем не менее по-прежнему предоставляют способ явно указать baseUri для относительного разрешение пути элементов <xsl:include> и <xsl:import> во время выполнения?

Попробуйте использовать :

XslCompiledTransform.CompileToType ()

Один из аргументов, который принимает этот статический метод: :

XmlResolver stylesheetResolver
0 голосов
/ 25 января 2012

Я не знаю, сломает ли это вашу систему, но как вместо того, чтобы

  1. компилировать с xsltc.exe
  2. развертыванием двоичного файла
  3. с загрузкойдвоичный файл с this Load()

вы

  1. разверните таблицы стилей, однако многие из них необходимы с директивами import/include
  2. загрузить основную таблицу стилей с помощью this Load(), указав преобразователь для import/incldue

Похоже, вы все равно получите преимущество от "скомпилированной" таблицы стилей,по крайней мере во время выполнения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...