在XSL样式表中,我正在尝试使用document()函数和xml文件的相对路径(如果我正确理解XSLT规范,这应该是可能的),但由于某种原因,它看起来不像加载文件。使用绝对URI的相同代码按预期工作。我正在尝试加载的XML文件与样式表位于同一文件夹中。
问题是,我是否遗漏了Coldfusion 8 XSLT解析器中的document()函数如何解析相对路径的问题?我正在使用XmlTransform来调用我的CF组件中的XSLT解析器。
文件夹结构(简体,docroot =域名,例如http://www.example.com/):
docroot/html/xsl/stylesheet.xsl
docroot/html/xsl/translations.xml
docroot/backend.cfc
调用文档函数的XSLT:
<h1>We should have hello after this text</h1>
<xsl:for-each select="document('translations.xml')">
<h2>hello</h2>
</xsl:for-each>
<h1>We should have hello before this text</h1>
在上面的代码中,如果我将document('translation.xml')
替换为document('http://www.example.com/html/xsl/translation.xml')
,代码将按预期工作。但是,我希望避免将域硬编码到语句中,因为它会使样式表变得不那么便携。
我正在尝试加载的XML:
<?xml version="1.0" encoding="utf-8"?>
<translations>
<fi>
<insured>Vakuutettu</insured>
</fi>
<se>
<insured>Försäkrad</insured>
</se>
</translations>
ColdFusion组件backend.cfc中的代码,它启动XSL解析器:
...
<cfoutput>#XmlTransform(obj, xsltProductTable04, xslParameters)#</cfoutput>
...
xsltProductTable04是一个指向我正在加载的样式表的变量,它的值为html/xsl/stylesheet.xsl
。我是否可以使用相对于cfc组件的URI加载样式表?
根据Dimitre Novatchev的建议,我尝试逐步删除URL的每个部分(例如/html/xsl/translation.xml,/xsl/translation.xml等),但这些组合都不起作用。甚至可以在URL的开头使用和不使用正斜杠来尝试。
我目前解决此问题的方法是在样式表之外构建一个绝对URL,然后将其作为参数传递给样式表。这是有效的,在我当前的项目中实际上是一个更好的解决方案,因为它允许我简化XSL,因为我不需要关心在XSL中选择正确的语言了。但它仍然只是原始问题的解决方法。如果有人有更多关于为什么CF表现的信息,那么我很乐意听到它。
答案 0 :(得分:3)
我没有对XSLT或xmlTransform()做过多少工作,但我读了docs,其中说:
如果XSLT代码包含具有相对路径的include语句,则ColdFusion将相对于XSLT文件的位置或XSL字符串(当前ColdFusion页面的位置)解析它们。
我测试了这两个,它们工作正常。您的问题似乎是您将XSL作为字符串传递给xmlTransform(),因此当XSLT处理器看到对“translations.xml”的引用时,它必须查看它相对于调用代码,而不是相对于原始XML文件(据其所知,它可能在任何地方:毕竟它收到的所有内容都是字符串)。
所以我可以通过制作两个mod之一来使你的代码工作:
第一个可以传入PATH文件,例如:
XmlTransform(obj, expandPath("xsl/stylesheet.xsl"), xslParameters)
这样xmlTransform()调用就知道了XSL文件的位置,所以知道如何计算相对于XSL文件本身的路径。
或者其次,将XSL文件中的translations.xml相对于代码而不是XSL文件,例如:
<xsl:for-each select="document('xsl/translations.xml')">
这两种方法都适用于我。我认为第一个更便于携带。
有意义吗?