作为我们的 Web 应用程序构建过程的一部分,我设置了要使用的 XSLT 样式表来构建微软的xsltc.exe http://msdn.microsoft.com/en-us/library/bb399405.aspx每当我们运行完整编译时。在本地开发期间,这非常有效,因为代码是在同一位置编译和托管的。然而,一旦将其放在构建服务器上,问题就出现了。
构建服务器将像我在本地一样编译 XSLT 样式表,但随后运行一个脚本,将编译后的代码部署到我们的内部临时 Web 服务器。一旦这些二进制文件从编译位置移动,相对路径<xsl:import>
and <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");
现在,我使用带有单个“Type”参数的 XslCompiledTransform.Load() 方法来引入基于 xsltc.exe 的预编译 XSLT 样式表。我可以从堆栈跟踪中看出,.NET 框架正在使用 XmlUrlResolver 来尝试解析这些外部样式表的实际位置,但我没有找到一种方法来提供 XmlResolver 的重写实现,我可以在其中传递新的baseUri 指向这些样式表在 Web 服务器上的位置。
我认为我可以通过不再使用 xsltc.exe 预编译并通过 XmlReaders 加载 XSLT 样式表来解决此问题,因为这将使我可以使用其他 XslCompiledTransform.Load() 方法 http://msdn.microsoft.com/en-us/library/system.xml.xsl.xslcompiledtransform.load.aspx其中有一个参数,我可以在其中提供我自己的 XmlResolver 实现。但是,我喜欢用于语法验证和性能的预编译选项,因此除非绝对必要,否则我不想放弃它。
有没有办法使用 xsltc.exe 预编译这些 XSLT 样式表,但仍然提供一种方法来显式声明相对路径解析的 baseUri<xsl:include>
and <xsl:import>
运行时的元素?