使用程序集在引用的 XSL 模板中编写脚本
有两个 XSL 文件。其中一个使用
包含另一个。主模板根据节点值决定调用哪些实际模板,并且包含的模板包含实际的转换规则。这里没什么特别的。
但包含的文件有一个脚本块:
<msxsl:script language="VB" implements-prefix="user">
<msxsl:assembly href="C:\Absolute\Path\MyEscaper.dll" />
<msxsl:using namespace="ZebraEscaper.MyCompany" />
<![CDATA[
Public Function escape(s As String) As String
Return EncodeField(s, True)
End Function
]]>
</msxsl:script>
user:escape() 函数稍后在包含的模板中使用。
现在,我进入 VS2008 XSLT 调试器。
主模板调用
并执行包含的模板。并且出现 FileNotFound 异常,“无法加载文件或程序集 'MyEscaper,Version=1.0.0.0,Culture=neutral,PublicKeyToken=null' 或其依赖项之一。系统找不到指定的文件。”
现在,如果我只访问包含的文件并执行它,就像它是一个独立的模板一样,不包含在任何内容中,那么一切都会正常。找到程序集并调用函数,但显然结果没有意义,因为模板设计为包含项。
那么问题来了——为什么当包含模板时系统找不到程序集?
更多信息
文档指出“程序集路径名被解析两次 - 一次在编译期间,一次在执行期间。”如果我故意在路径中输入错误,我会得到相同的 FileNotFound 异常,但格式不同,系统表示找不到 file://C:\Absolute\Path\MyEscaper.dll。但是,当路径正确时,异常声称找不到 MyEscaper.dll, version=blabla, public token=null,并且该异常发生在 .Net 创建的 CompiledStylesheet.dll 中。我相信已编译的样式表被告知按名称调用程序集,而不是按 href 调用程序集,并且由于它不在临时文件夹中,因此调用失败。
为什么会这样呢?绝对路径在哪里以及为何被(错误地)转换为相对路径,以及如何控制它?
There are two XSL files. One includes another using an <xsl:include>
. The main template decides which actual templates to call depending on node values, and included templates contain actual transformation rules. Nothing special here.
But included file has a script block:
<msxsl:script language="VB" implements-prefix="user">
<msxsl:assembly href="C:\Absolute\Path\MyEscaper.dll" />
<msxsl:using namespace="ZebraEscaper.MyCompany" />
<![CDATA[
Public Function escape(s As String) As String
Return EncodeField(s, True)
End Function
]]>
</msxsl:script>
The user:escape() function is later used in the included template.
Now, I go to VS2008 XSLT debugger.
The main template calls <xsl:apply-templates>
and the included template executes. And a FileNotFound exception occurs, "Could not load file or assembly 'MyEscaper, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. The system cannot find the file specified."
Now, if I go to just the included file and execute it as if it was a standalone template, not included into anything, everything works. The assembly gets found and the function gets called, but obviously results don't make sense as the template designed to be an inclusion.
So the question -- why can't the system find the assembly when the template is included?
More information
Documentation states that "The assembly path name is resolved twice - once during compilation and once during execution." If I intentionally make a typo in the path, I get same FileNotFound exception, but formatted differently, where the system says it cannot find file://C:\Absolute\Path\MyEscaper.dll. However, when the path is correct, the exception claims it couldn't find MyEscaper.dll, version=blabla, public token=null, and that exception occurs in CompiledStylesheet.dll created by .Net. I believe that the compiled stylesheet is told to call the assembly by name, not by href, and since it's not in its temporary folder, the call fails.
Why so? Where and why does an absolute path get translated (wrongly) into a relative one, and how do I control it?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
所以。
由于某种原因,在包含的场景中,程序集的路径在编译期间和执行期间以不同方式解析。为什么会这样,我也没有任何线索。
只找到了两个合理的解决方案:
将所有代码从引用的程序集中移动到 XSL 模板中,使其成为嵌入式脚本。对于小的辅助函数来说,这实际上是首选。否则,
使用强名称对引用的程序集进行签名,将其添加到 GAC,并使用
name
(而不是href
)从模板中引用它。这样,在编译和执行过程中,程序集就会以相同的方式查找并找到。So.
For some reason, in an included scenario path to the assembly is resolved differently during compilation and during execution. Why it is so, I haven't got a clue.
Only two sane solutions were found:
Move all code from the referenced assembly into the XSL template, making it an embedded script. In case of small helper functions that is actually preferred. Otherwise,
Sign the referenced assembly with a strong name, add it to the GAC, and refer to it from templates using
name
, nothref
. This way the assembly will be looked up in the same way during compilation and execution, and will be found.