XSLT Explorer is an XSLT stylesheet that performs a small amount of static analysis on an XSLT stylesheet and publishes the results in HTML. The idea is that it gives you an overview of the structure of your stylesheet.
Explorer identifies templates, functions, and variables within each module. It attempts to show you any that are unused, shadowing other globals, or are used only once in another module.
The output from the explorer is a web page. Here’s an example
(from test.xsl
in the test suite):
This screen shot shows one parameter, one variable, and two templates. Each section shows relevant properties about the declaration: names, types, modes, etc., what other declarations refer to it, and what declarations it references. Each of the references is a link to the referent.
If line numbers were enabled, § is a link to the declaration in the source. If a template or function is recursive, that’s indicated by ♻︎. Three noteworthy conditions are identified:
- ☞
- Points out declarations that are unused.
- ⚠︎
- Points out (global) declarations that shadow earlier ones.
- ☝︎
- Points out declarations that are declared in one module but used exclusively only in one other module. (Candidates to be moved, perhaps?)
In match templates, the match is indicated as ≅ a list of elements. The match attempts to capture the list of elements involved, but all predicates are stripped away. (The explorer can’t practically make use of them, and removing them simplifies the display.)
Starting in version 0.1.6, comments containing the string “FIXME:” are also highlighted.
An interactive example of the explorer run on itself is online at https://xslt.xmlexplorer.com/ouroboros/.
- Download the distribution and unpack it somewhere.
- Transform your stylesheet with
xslt/explorer.xsl
. - Point your browser at the output! If you put the output in the same directory where you unpacked the distribution, it’ll just work. If you want to put it somewhere else, copy the CSS and JS directories appropriately.
If you are using Saxon PE or EE, use the `-l` (lowercase “L”) option to include line numbers.
The following parameters control aspects of the output:
source-listings
- If “false”, the source code listings will not be included. (Default=“true”)
format
- The usual output format is an HTML page. Select “data” for a plain XML summary of the results. (Default=“html”)
In addition, there are some debugging flags:
debug-parse
- If not empty, the intermediate parser output will be stored there.
debug-resolve
- If not empty, the intermediate resolved output will be stored there.
debug-analyze
- If not empty, the intermediate analyzed output will be stored there.
xspec-tests
- If “true”, a few small tweaks are made to the results so that irrelevant differences between the dev environment and the CI environment don’t cause spurious test failures. (Default=“false”)
- See the issues list.
- The trick where it links from the instruction to the source code depends on having the CSS configured so that the line numbers align with the lines in the Prism listing.
- The output isn’t especially accessible. A more accessible transformation of the “data” output should be possible.
XSLT is perfectly capable of analyzing the XML structure of your stylesheet. To extract information from XPath expressions, it uses an XPath 3.1 parser generated by Gunther Rademacher’s always excellent REx Parser Generator.
One consequence of doing the XPath parsing in XSLT is that very, very large XPath expressions may have quite poor performance. To attempt to workaround this, a primitive test is made first: if an expression does not contain any “(“ or “$” characters, then it can’t contain any function calls or variable references.
The XPath 3.1 parser contains a 60K XPath expression that brings the
parser to its knees. This quick check avoids that expression. If you want to avoid parsing a module entirely,
stick <?xsltexplorer-skip-import?>
immediately in front of the import statement
(or <?xsltexplorer-skip-include?>
in front of an include statement).
With the XPath parsing sorted, the code takes a multi-pass approach:
- Parse the structure, loading imports and includes into a flat structure.
- Parse that structure to identify function calls, template calls, and variable references.
- For those references, work out what actual instruction they refer to, taking into consideration the possibility of shadowing.
- Extract the details of the analysis into a simple XML document.
- Transform that document into HTML.