Some of our XML documents contain "included" subdocuments.
I have a pre-processor stylesheet which replaces every
<include href="relative-path-to-doc" />
..content from included document..
Framemaker runs this correctly when loading the outer document and all the subcontent is included. The stylesheet calls
to do this and the relative-path-to-doc is evaluated relative to the outer document which was passed to the pre-processor.
The problem I am having is when the full document is saved. There is a complementary post-processor stylesheet which is supposed to identify any
replace the included element with the include element in the output document, and process all the included content within
<xsl:result-document href="relative-path-to-doc"><xsl:apply-templates ... /></xsl:result-document>
When I run this stylesheet outside of Framemaker it correctly creates the result-document relative to the primary document, regardless of where I call the stylesheet from. Document() and xsl:result-document() are correctly complementary. But within Framemaker it fails with the error
Fatal Error at file C:\Program Files (x86)\Adobe\Adobe FrameMaker 2017\structure\xml\helpcenter\app\post.xsl, line 40, char -1, Message: java.io.FileNotFoundException: Access to the path 'C:\Program Files (x86)\Adobe\Adobe FrameMaker 2017\formats_sub.xml' is denied.
Is this a bug? How could I achieve what I am trying to do here?
I am not fully able to follow the stylesheet flow, maybe because I've never done anything quite the way that you are. But I thought I might ask a more basic question, which I hope is not insulting. It appears that your stylesheet is attempting to write within the Windows Program Files area, which is typically not writeable by an application. For example, an FM plugin cannot write into the installation area. Could that be the problem? Could you move your structure app files out of Program Files and try it again?
The pre and post processing stylesheets are both located within Frame's $STRUCTDIR (in $STRUCTDIR/xml/application/app to be specific). That's where I understood they had to be when I learned Structured Frame with FM7 and FM8. You are correct that the error I am getting is because the post-processor stylesheet is trying to write the output file relative to the location of the stylesheet rather than the location of the file that was being edited. The thing is, that's not how it behaves when I run it external to Framemaker: then it creates the result document relative to the path of the original file.
First, a side issue. It is not necessary to put your applications in $STRUCTDIR. You can put them in any directory that is convenient. $STRUCTDIR is simply a convenient location to group files for various applications.
To return to the main point, according to Michael Kay, editor of the XSLT standard, in XSLT 2.0 and XPath 2.0, 4th edition, "The way in which the href attribute is used is deliberately left a little vague..., because the details are likely to be implementation-dependent...ny relative URI used in the href attribute... is interpreted relative to a Base Output URI, which in...
Thus, the fact that different processors give different results is not a bug. You can avoid relative URIs by using base-uri() to retrieve the absolute URI to the input document and set href relative to the base URI. The resolve-uri() function might also be helpful.
OK, I should have been aware that href was a bit nebulous in this situation, so thanks for the clarification.
Specifying a stylesheet location in a less restrictive part of the filesystem would avoid the permissions error which I am currently getting, but it would not solve my problem because the relative location of the primary document is not necessarily derivable from the spreadsheet location, so the current copy of the stylesheet would not always update the included subdocuments in the location from which they had been originally read.
Regarding base-url(), I'm not sure what Frame's workflow is here. If I open /my/docs/folder/doc.xml in (structured) Frame, I believe it first executes the pre-process XSL stylesheet to produce a temporary xml file which is then imported/converted into a Frame document using my read/write rules before displaying the document in the editor. Is the temporary xml document also in /my/docs/folder? Because I presume that document, not my original, is what is going to be used to determine base_url().
The XPath function base-uri() will return the URI of the primary document. I tested that I get the same result using Saxon PE from the command line or Saxon HE from a FrameMaker structured application. In both import and export the value is correct.
When FrameMaker opens an XML file it applies the xslt to the source XML file and saves that as a temporary file in your %temp% folder. That temp file is immediately deleted once the XML file is open in FrameMaker. This temporary file never has any effect on the value of the base-uri() because it is never used as the source file. In both directions it is the source XML file that defines the base-uri.
I have used a similar approach for including other documents, effectively implementing XInclude through XSLT. It works well, so your process should only require a little adjustment to do exactly what you need.
Time to resurrect this thread because at last the project is proceeding.
You suggested that I don't need to put the application definitions in the $STRUCTDIR folder; they (and in particular the XML stylesheet paths) could be anywhere.
My question now is, if I want to define the path of (say) the pre-processing stylesheet, can I use an environment variable as part of that path? So not Frame's $STRUCTDIR, but a Windows environment variable which could be assigned appropriately for every user?
This may be due to security on the folder you are saving to. For the last few versions of Windows, the Program Files folders and sub-folders have been subject to write restrictions. Try to save your files in a different location where saving is unrestricted.
You may need to provide the new path to the xsl stylesheet as a parameter in the XML Application definition in structapps.fm.
I hope this makes the difference.
Thank you, you've all provided pieces of the puzzle and the problem is solved. It's hard to pick one particular answer as the correct one when you've all contributed, what should I do?!