This blog post tells you all you need to know to make the most of FrameMaker’s XSLT support – including choice of XSLT processors, using parameters, adapting smart paste behavior, running XSLT from ExtendScript or in code view, and installing another XSLT processor version in your FrameMaker environment.
Why XSLT support is important
Even if most technical authors are not aware of it, XSLT is an important part of their work today. It is what makes modern content creation and publishing systems function, and work together. Any web output from any document processing system will be using at least some XSLT, if not a whole lot of it. XSLT allows converting an XML document into anything else – another XML document, HTML, plain text, even a MIDI file that can be played on your sound system.
Where XML is the basic unified alphabet in which we define the structure for our content (using a myriad of XML standards, depending on our business domain and personal preferences), XSLT is the universal machine translation engine, enabling automated conversions between all these dialects. Structured FrameMaker would not be half as powerful without extensive XSLT suport.
The following sections show you all the points where XSLT is being applied in FrameMaker 2017 and, more importantly, where you can influence the various transformations. There is much more to write about all the options, so this blog post is only covering the basics. For more information, you are welcome to contact the author.
Under-the-hood XSLT usage in FrameMaker
Even if you are not aware of it, FrameMaker may be using XSLT whenever you open, save or paste clipboard contents into a structured document. Which transformations are being applied is determined by settings in your structured application and in the smart paste options. Apart from these more or less hidden applications of XSLT, there are also ways to explicitly run a transformation, by calling an XSLT from ExtendScript, or by running transformations in the XML view. The following list gives some details about each of these methods.
Importing and exporting structured content
The DOCTYPE of an XML document defines which structured application is called when reading the document into FrameMaker, or when saving the document back to XML. The structured application definition has an optional XSLT Preferences section, in which the XSLTs for import and output can be defined.
The stylesheet for Preprocessing is applied on import, before the read-write rules kick in. This allows renaming elements or attributes, or possibly completely reshuffling the XML before FrameMaker attempts to read the contents. On the way out, an optional Postprocessing stylesheet is applied after the read-write rules. Parameters can also be passed to the stylesheets.
Let’s assume, we want to do some pre-processing of a DITA 1.3 topic file before we open it in FrameMaker and some post-processing when we close it. To do this we open the “Structured Application Designer” (Menu > Structure > Structured Application Designer) and enter the path and file name to the XSLT Prefences.
In this example we add an XSLT “Assign-IDs-to-Elements.xslt” that processes the DITA XML before it opens it in FM. This is the “Pre Processing Stylesheet. It scans the DITA XML file for elements that do not have an ID attribute yet and assigns an ID to those elements automatically. In addition we assign XALAN as the XSLT Processor.
In addition we assign a “Post Processing Stylesheet”: “
Create Change Report.xslt“. It creates a backup of the DITA XML file before opening it in FrameMaker. When we change th the DITA file and save it, it compares the old file with the new one and automatically creats a change report for us. For this post processing we specify SAXON as the XSLT processor.
structapps.fm it looks like this:
The structapps.fm is located in
In recent years, a lot of development effort was put into creating the smart paste option in structured FrameMaker. This feature allows copying content from Microsoft Word, a web browser or another application, and pasting it into a DITA topic. This feature is implemented using XSLT and the good news is that you can replace the XSL if you need it to work in a different manner. The smart paste XSLTs are an optional part of the structured application definitions, as shown in this excerpt.
Running XSLT in Code View
When you switch to FrameMaker’s Code View, the XML content of your document is shown as plain text with tags and attributes. If you were viewing a document in WYSIWYG view, the document will be written to XML (using the read-write rules and possible Postprocessing stylesheets defined for the doctype in the structured application – see the previous section). Once the XML is created and saved, you can run transformations on this XML from the XSLT menu.
Before you apply an XSLT, you must select one, and there are several ways to do so. First of all, you can select a specific XSL file. However, browsing your file system to find the required XSL file may become tedious when you have a number of different scenarios. To make life a lot easier, the transformation file was created. This is an XML file that names transformations and supplies the path to the XSL file and optionally sets parameter values for each.
FrameMaker allows choosing between the default transformation file or one of your own that you have stored anywhere on your file system. But you can also associate transformation files with particular document types via the structured application definitions. The entry in your structured application definition is aptly called Transformation File and points to a transformation XML file that you may place anywhere on your file system.
With all these options available, it becomes quite efficient to select the desired transformation from the dialog, which pops up when choosing Manage Transformations or when no transformation has yet been selected:
Once you have selected the transformation file, the scenarios defined in that file are listed in the dialog, allowing you to quickly select the desired transformation and set it as the active one. Then click the Run button to execute the transformation. The Advanced Run option allows running the transformation on all open XML files, or on all XML files in a specific folder. This can greatly enhance your lunch or coffee break productivity.
Making XSLT part of your ExtendScript automation
One more area where you may want to use XSLT is ExtendScript. In several automation projects, I have completed over the past years, this has been a vital addition. Not all the transformations you want to do can be attached to the events of opening or saving a particular XML file, after all. With access to the XSLT processing engines from ExtendScript, there is virtually no limit to the level of automation you can achieve.
This functionality is not (yet) documented in the Scripting Guide, so you may want to keep a pointer to this blog post in your bookmarks for future reference
The engine that runs the XSLT processor can be called via the CallClient( ) method (which is used for any interaction between scripts and one of the installed clients in FrameMaker. The name of the client that starts the XSLT processor and passes all arguments to it is FmXSLT. The arguments are listed in the table below. The argument string holds the command XSLTRunTrScenario followed by a list of arguments:
||full path to the XML file to be transformed||No|
||full path to the XSL file||No|
||full path to the output file to be created||No|
||one of the names defined in maker.ini||Yes|
||parameter name and value||Yes|
As this can become quite a tedious job to do, I have created a small script file with functions thar set all arguments as properties in an XSLT Object and then calls the transform. If you are interested in this, drop me a mail and I will make it available to you. This capability has certainly made a difference in my recent project work.
Which XSLT processor?
The FrameMaker 2017 product comes with two pre-installed XSLT processors: XALAN and SAXON.
XALAN (see xalan.apache.org) is part of the Apache open source project and has been around for a long time. Because of its Open Source nature, the scope is necessarily limited (as resources are) and even though XSLT has evolved quite a bit, XALAN still only supports XSLT 1.0 and XPath 1.0.
SAXON (see www.saxonica.com) is the stripped-down free version of a commercial product. As the company behind this processor, UK-based Saxonica, is making money selling the full version of the product, they can afford to keep up with developments in the standard. This is further helped by the fact that the founder of Saxonica, Michael Kay, has been chair of the XSLT standards committee ever since version 1.0. He is also the author of the 1,316-page XSLT 2.0 and XPath 2.0 ‘bible’. The SAXON-HE (Home Edition) version shipped with Framemaker 2017 supports XSLT 2.0 and XPath 3.0.
If your transformation needs exceed what these two in-the-box processors have to offer, you can also add another XSLT processor to the options (see Installing and activating another XSLT processor below).
Differences in XSLT versions
Moving from XSLT 1.0 to XSLT 2.0 meant the addition of a number of important features, which are described in detail in this article by Evan Lenz. The most important aspects are:
- Conversion of result tree fragments to node sets. This means that you can now assign the result of a transform to a variable, which can then be used as the source to be transformed by another template. This allows for multi-pass transformations without the need to store transformation results in a temporary file, on which a second XSLT is then applied. As the style sheets called on XML import and output, and the ones called on smart paste, only allow a single transformation to be executed, this is an important feature for running XSLT in FrameMaker.
- Multiple output documents. Depending on your use case, this may or may not be important. I have personally created a structured application that takes a single, very large, XDocBook file and splits it into 400 manageable single XML files. Without this XSLT ability, chunking large files into smaller components would require ExtendScript or Visual C++ programming in the FDK.
- Built-in support for grouping. This may be useful when processing XML documents that hold large sets of data, which you need to shuffle into ordered sections or table rows. Grouping elements based on certain attribute values could be done in XSLT 1.0, but sometimes required a lot of code. This has become very efficient with the new
<xsl:for-each-group>element in XSLT 2.0.
- User-defined functions. With the new
<xsl:function>it becomes much easier to define reusable pieces of XSLT to be called from multiple templates throughout your code. Before, you would have to create named templates and possibly use mode attributes. With a large set of reusable functionality, this could become quite chaotic and hard to debug.
XSLT 2.0 was established in 2007. Moving on, the XSLT committee defined another set of extensions, which were released with XSLT 3.0. As most of the additions in XSLT 3.0 relate to streaming, packaging and debugging, they may be of less importance for the types of transformations to be executed within FrameMaker. For this reason, I am skipping an overview of XSLT 3.0 here and pointing those who are terribly interested in the latest and greatest to this slide deck by Jakub Malý.
Installing and activating another XSLT processor
The available XSLT processors are defined in the
maker.ini file, in the
[XSLTProcessors] section. To replace the current version of an XSLT processor, install the package on your computer and change the path in the
maker.ini file to point to the new installation. When using a relative path, the starting point is the home directory of the FrameMaker product.
Adding a processor is almost as easy. Just add a line to the
maker.ini file and choose a unique name for the processor to be added to the list. After restarting FrameMaker, the new processor will be available in the various locations where you can choose the XSLT processor to be used. Move the
Default keyword to the end of the required line.
Here is an example of my
maker.ini file with the two commercial versions of the Saxon processor added to the list of available processors. The names at the start of the lines appear in dialogs and files (such as the structured application definitions).
;----------- XSLT Processor ------------------------------
SAXON-PE=C:\Program Files (x86)\saxon\saxonpe9-6-0-10j\saxon9pe.jar, net.sf.saxon.TransformerFactoryImpl
SAXON-EE=C:\Program Files (x86)\saxon\saxonee9-7-0-18j\saxon9pe.jar, net.sf.saxon.TransformerFactoryImpl
There may be a lot more to show about the power of XSLT under the hood, as well as out in the open, in Adobe FrameMaker 2017. I have only been able to outline the main mechanisms in this blog post. If you are interested in more details on a particular item, get in touch.