开发者

calling xslt document() function with relative path in coldfusion 8

开发者 https://www.devze.com 2023-04-13 06:17 出处:网络
Within an XSL stylesheet, I\'m trying to use the document() function with a relative path to an xml file (which should be possible if I understand the XSLT specs correctly), but for some reason it doe

Within an XSL stylesheet, I'm trying to use the document() function with a relative path to an xml file (which should be possible if I understand the XSLT specs correctly), but for some reason it doesn't seem to load the file. The same code using an absolute URI works as expected. The XML file I'm trying to load is in the same folder as the stylesheet.

The question is, am I missing something in regards to how the document() function in the Coldfusion 8 XSLT parser resolves relative paths? I'm using XmlTransform to invoke the XSLT parser in my CF component.

The folder structure (simplified, docroot = domain, e.g. http://www.example.com/):

docroot/html/xsl/stylesheet.xsl 
docroot/html/xsl/translations.xml
docroot/backend.cfc

The XSLT that calls the document function:

<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>

In the above code, if I replace document('translation.xml') with document('http://www.example.com/html/xsl/translation.xml'), the code works as expected. However, hard coding the domain into the statement is what I would like to avoid as it makes the stylesheet less portable.

The XML I'm trying to load:

<?xml version="1.0" encoding="utf-8"?>
<translations>
    <fi>
        <insured>Vakuutettu</insured>
    </fi>
    <se>
        <insured>Försäkrad</insured>
    </se>
</translations>

The code in the ColdFusion component backend.cfc, which starts the XSL parser:

...
<cfoutput>#XmlTransform(obj, xsltProductTable04, xslParameters)#</cfoutput>
...

xsltProductTable04 is a variable which points to the stylesheet I'm loading, and it has the value html/xsl/stylesheet.xsl. Could it make a difference that I'm loading the stylesheet using a URI relative to the cfc component?

Update

As per Dimitre Novatchev's suggestion, I tried removing every section of the URL step by step (e.g. /html/xsl/translation.xml, /xsl/translation.xml etc.), but none of the combinations work. Even tried alternatively with and without the forward slash in the beginning of the URL's.

Update 2

My current workaround to this issue is to build 开发者_如何学编程an absolute URL outside of the stylesheet and then pass it in as an argument to the stylesheet. This works, and in my current project actually turns out to be a better solution because it allows me to simplify the XSL, since I don't need to care about selecting the correct language inside the XSL anymore. But it's still only a workaround to the original issue. If anyone has more info on why CF behaves as it does, then I'd be happy to hear it.


I've not done much with XSLT or xmlTransform(), but I read the docs, which say this:

If the XSLT code contains include statements with relative paths, ColdFusion resolves them relative to the location of the XSLT file, or for an XSL string, the location of the current ColdFusion page.

And I tested both of those, and they work fine. What seems to be your problem is that you're passing the XSL as a string to xmlTransform(), so when the XSLT processor sees the reference to "translations.xml", it has to look at it relative to the calling code, rather than relative to the original XML file (which as far as it knows could have been anywhere: all it received was a string, after all).

So I can make your code work by making one of two mods:

First one could pass in the file PATH, eg:

XmlTransform(obj, expandPath("xsl/stylesheet.xsl"), xslParameters)

That way the xmlTransform() call knows where the XSL file is, so knows how to work out paths relative to the XSL file itself.

Or secondly, make the ref to translations.xml in the XSL file relative to the code not the XSL file, eg:

<xsl:for-each select="document('xsl/translations.xml')">

Both of those approaches works for me. I think the first one is more transportable, though.

Make sense?

0

精彩评论

暂无评论...
验证码 换一张
取 消