The EUROCONTROL Electronic AIP Specification is provided with a set of XSLT style sheets meant as an example of how an eAIP XML document can be converted into HTML and XSL-FO formats. The HTML style sheet is designed to present an AIP on a Web site, be it an intranet or a public site; it follows most of the eAIP Usability Guidelines. The XSL-FO style sheet was developed in order to generate a paper version of an eAIP. This document describes how the XSLT style sheets are structured and explains how the "content logic" was separated from the presentation logic.
Readers are expected to have at least a basic knowledge of XSLT. The following resources might be a good place to start: XSLT 1.0 W3C Recommendation; D. Pawson's XSLT FAQ..
By content logic, we mean the XSLT code that produces the actual text and data (the content) which compose an AIP. For example, a section title is marked up as such in the XML eAIP document and is copied into the generated HTML and XSL-FO documents, possibly with an automatically-generated numbering. In this case, some content logic may be needed to compute the title numbering.
By presentation logic, we mean the XSLT code that produces the formatting and styling necessary to present the content on the target format (HTML, XSL-FO and others). Continuing with our title example, the title content is typically surrounded by formatting mark-up such as a h1-h6 element in HTML or a block element in XSL-FO. These elements would possibly contain styling mark-up such as a class in HTML and font-related attributes in XSL-FO. Output of these elements and attributes is part of the presentation logic.
Presentation logic is specific to each target format, while content logic can generally be re-used for any format. Still with our title example, the numbering computed by the content logic is exactly the same for HTML and XSL-FO. In fact, it should probably be the same for any target format, because numbering is considered to be part of the content. Even though the AIP editors marked the title to be automatically numbered, the number produced must be the same for all target formats.
The style sheets are split in 3 groups:
Generic style sheets are prefixed with "g-"; example: g-block.xslt;
HTML-specific style sheets are prefixed with "html-"; example: html-block.xslt;
XSL-FO-specific style sheets are prefixed with "fo-"; example: fo-block.xslt.
Generic style sheets contain the "content logic". They are normally imported by formatting-specific style sheets. Generic style sheets do not generate any element. They generate the content (the text) that must be produced automatically (such as for auto-numbering) and combine the various pieces of content together where needed.
It is mostly within generic style sheets that eAIP elements are matched by templates. These templates deal with content logic that need to be applied before calling a formatting-specific template. The formatting template should be overridden by a calling style sheet if any formatting is needed, but it is not mandatory.
These style sheets contain formatting templates specific to HTML. Templates in these style sheets override named presentation templates defined in generic style sheets.
These style sheets contain formatting templates specific to XSL-FO. Just like in HTML-specific style sheets, templates in these style sheets override named presentation templates defined in generic style sheets.
This table list all XSLT files alphabetically with a short description of their purpose. See also the elements to XSLT files mapping table, which indicate where each element is processed.
Table 5.1.
Generic | HTML | XSL-FO | Description |
---|---|---|---|
- | html-amdt-list.xslt | - | Generates a list of all changes in a given AMDT (in development) |
g-amendments.xslt | html-amendments.xslt | fo-amendments.xslt | Amendment elements and attributes, including 0.2 sections |
- | - | fo-att-set.xslt | Generic templates for dynamic class name/attribute-set processing (see below, Dynamic Attribute-set Processing for details) |
g-block.xslt | html-block.xslt | fo-block.xslt | Processing of block elements such as Address and div |
- | - | fo-checklist.xslt | Generation of the checklist of pages in GEN-0.4 |
g-content.xslt | html-content.xslt | fo-content.xslt | Initialisation of common variables and parameters, plus eAIP element processing for HTML |
g-eAIC-eSUP.xslt | html-eAIC-eSUP.xslt | fo-eAIC-eSUP.xslt | Elements and attributes related to Circulars and Supplements documents (but not the Supplement element used in an eAIP document |
g-generic.xslt | html-generic.xslt | fo-generic.xslt | Common templates used for many elements; default templates |
g-gettext.xslt | - | - | A generic set of templates to retrieve the localisation of words and sentences |
g-graphics.xslt | html-graphics.xslt | fo-graphics.xslt | Templates related to Figure and Graphic-file elements |
g-inline.xslt | html-inline.xslt | fo-inline.xslt | Processing of inline elements such as Abbreviation and strong |
g-links-s.xslt | html-links-s.xslt | fo-links-s.xslt | Generation of links within an eAIP document |
g-lists.xslt | html-lists.xslt | fo-lists.xslt | Processing of list elements such as Location-definition and ul |
- | html-menu.xslt | - | Generation of the table of contents for the HTML navigation interface |
g-numbering.xslt | html-numbering.xslt | fo-numbering.xslt | Auto-numbering templates |
- | - | fo-pages.xslt | Page layouts, page headers and footers |
g-structure.xslt | html-structure.xslt | fo-structure.xslt | Processing of structural elements such as Sub-section, sections, chapters and Title elements |
- | - | fo-styles.xslt | Definition of style classes for XSL-FO; conceptually equivalent to the eAIP.css file in HTML |
g-supplements.xslt | html-supplements.xslt | fo-supplements.xslt | The Supplement in an eAIP document and related templates |
- | html-table.xslt | fo-table.xslt | Processing of tables-related elements (especially for XSL-FO) |
g-tables-ENR.xslt | html-tables-ENR.xslt | fo-tables-ENR.xslt | All ENR part specific elements, such as Route, Designated-point and Navaid |
g-toc.xslt | html-toc.xslt | fo-toc.xslt | Generation of tables of contents (0.6 sections) |
In order to separate as much as possible content from presentation, the XSLT code was split in three parts. Most elements are handled by two or three templates. For the sake of this documentation, let's call them "the matching template", "the presentation template" and "the content template".
In general, templates will only process one element or one attribute (though presentation templates might generate several elements and attributes as needed). Therefore, attributes may have their own set of three templates.
Matching templates are generally defined in generic style sheets. Most often, they will simply call the relevant presentation template. In some cases, they contain some content logic that needs to be applied before any formatting. The table of content is an example of such case. Matching templates are normally re-used for any target format.
When content cannot be fully separated from presentation, matching templates are defined in formatting-specific style sheets as well and they then override generic matching templates. Two XSLT mechanisms can then be used: the fact that templates defined within the importing style sheet will always override an imported template with the same priority; or by using a more specific matching expression in the importing style sheet.
In most cases, presentation templates generate a formatting-specific element or attribute, which depends on the specific formatting targeted. They call the content template within the generated element. Default presentation templates (in generic style sheets) do nothing but call the relevant content template.
The Designated-point element gives us a complete example:
A Designated-point can be listed or not in the Designated-points table. If the Listed attribute is set to "Yes", then the Designated-point's entry in the table is generated. This if-clause is common to both HTML and PDF presentations, so the relevant code is located in the generic style sheet (g-tables-ENR.xslt), in this matching template.
<xsl:template match="e:Designated-point">
<xsl:if test="@Listed='Yes'"><!-- foreign points are not listed -->
<xsl:call-template name="Designated-pointStyle"/>
</xsl:if>
</xsl:template>
In HTML as in XSL-FO, a table row is generated for each (listed) designated-point. However, the table row element in HTML is not the same as the one for XS-FO. Also, the XSLT code to show amendments in HTML is different to the one in XSL-FO. Hence, these two quite different templates, first for HTML (html-tables-ENR.xslt):
<xsl:template name="Designated-pointStyle">
<tr>
<xsl:apply-templates select="@*"/>
<xsl:call-template name="Designated-pointContent"/>
</tr>
</xsl:template>
And then for XSL-FO (fo-tables-ENR.xslt):
<xsl:template name="Designated-pointStyle">
<xsl:if test="@Updated != 'Deleted'">
<fo:table-row>
<xsl:apply-templates select="@*[not(starts-with(local-name(), 'Updated'))]"/>
<fo:table-cell xsl:use-attribute-sets="AmdtCell">
<xsl:apply-templates select="@Updated"/>
<xsl:apply-templates select="e:Designated-point/@Updated-ref"/>
<fo:block><xsl:call-template name="DeletedMarkRoute"/> </fo:block>
</fo:table-cell>
<xsl:call-template name="Designated-pointContent"/>
</fo:table-row>
</xsl:if>
</xsl:template>
While being quite different, they have one mandatory line in common (line 4 for HTML and line 10 for XSL-FO): the call to the content template, which contains the rest of common XSLT code.
Back to the generic style sheet, where the "Designated-pointContent" template calls the relevant templates to process the content of a Designated-point element:
<xsl:template name="Designated-pointContent">
<xsl:apply-templates select="e:Designated-point-ident"/>
<xsl:apply-templates select="e:Latitude"/>
<xsl:call-template name="Designated-pointRouteStyle"/>
</xsl:template>
There are three "main" style sheets: html-content.xslt for HTML pages, html-menu.xslt for the HTML Navigation menu (ToC) and fo-content for FO files. These 3 files import many other files, which handle specific groups of eAIP elements.
The following table shows which XSLT file handle each element.
Table 5.2.
Element | For XHTML | For XSL-FO | Element | For XHTML | For XSL-FO |
---|---|---|---|---|---|
/ (document root) | - | pages | Abbreviation | inline | inline |
Abbreviation-description | lists | lists | Abbreviation-details | lists | lists |
Abbreviation-ident | lists | lists | AD, AD-x, AD-x.y | structure | structure |
Address | block | block | Address-part | block | block |
Aerodrome | structure | structure | Affects | supplements | supplements |
Amendment | supplements | supplements | Date-time | inline | inline |
Deleted | amendments | amendments | Designated-point | tables-ENR | tables-ENR |
Designated-point-ident | tables-ENR | tables-ENR | Designated-point-table | tables-ENR | tables-ENR |
eAIC | eAIC-eSUP | - | eAIP | content | - |
eAIP-reference | eAIC-eSUP | eAIC-eSUP | ENR, ENR-x, ENR-x.y | structure | structure |
eSUP | eAIC-eSUP | - | Figure | graphics | graphics |
GEN, GEN-x, GEN-x.y | structure | structure | Generated (in AD 2.1 & 3.1) | structure | structure |
Generated (in sections 0.6) | toc | toc | Graphic-file | graphics | graphics |
Heliport | structure | structure | Inserted | amendments | amendments |
Latitude (Designated-point) | tables-ENR | tables-ENR | Latitude (Navaid) | tables-ENR | tables-ENR |
Location | inline | inline | Location-definition | lists | lists |
Location-ident | lists | lists | Location-name | lists | lists |
Location-table | lists | lists | Longitude (Designated-point) | tables-ENR | tables-ENR |
Longitude (Navaid) | tables-ENR | tables-ENR | Navaid | tables-ENR | tables-ENR |
Navaid-declination | tables-ENR | tables-ENR | Navaid-elevation | tables-ENR | tables-ENR |
Navaid-frequency | tables-ENR | tables-ENR | Navaid-hours | tables-ENR | tables-ENR |
Navaid-ident | tables-ENR | tables-ENR | Navaid-indication | tables-ENR | tables-ENR |
Navaid-indication-distance | tables-ENR | tables-ENR | Navaid-indication-radial | tables-ENR | tables-ENR |
Navaid-magnetic-variation | tables-ENR | tables-ENR | Navaid-name | tables-ENR | tables-ENR |
Navaid-remarks | tables-ENR | tables-ENR | Navaid-table | tables-ENR | tables-ENR |
Navaid-type | tables-ENR | tables-ENR | NIL | structure | structure |
Not-applicable | block | block | References | eAIC-eSUP | eAIC-eSUP |
Route | tables-ENR | tables-ENR | Route-designator | tables-ENR | tables-ENR |
Route-remark | tables-ENR | tables-ENR | Route-RNP | tables-ENR | tables-ENR |
Route-segment | tables-ENR | tables-ENR | Route-segment-airspace-class | tables-ENR | tables-ENR |
Route-segment-ATC | tables-ENR | tables-ENR | Route-segment-COP | tables-ENR | tables-ENR |
Route-segment-length | tables-ENR | tables-ENR | Route-segment-lower | tables-ENR | tables-ENR |
Route-segment-lower-override | tables-ENR | tables-ENR | Route-segment-mag-track | tables-ENR | tables-ENR |
Route-segment-minimum | tables-ENR | tables-ENR | Route-segment-remark | tables-ENR | tables-ENR |
Route-segment-remark-reference | tables-ENR | tables-ENR | Route-segment-reverse-mag-track | tables-ENR | tables-ENR |
Route-segment-reverse-true-track | tables-ENR | tables-ENR | Route-segment-RNP | tables-ENR | tables-ENR |
Route-segment-true-track | tables-ENR | tables-ENR | Route-segment-upper | tables-ENR | tables-ENR |
Route-segment-usage | tables-ENR | tables-ENR | Route-segment-usage-direction | tables-ENR | tables-ENR |
Route-segment-usage-level-type | tables-ENR | tables-ENR | Route-segment-usage-reference | tables-ENR | tables-ENR |
Route-segment-width | tables-ENR | tables-ENR | See-supplement | supplements | supplements |
Significant-point-ATC | tables-ENR | tables-ENR | Significant-point-description | tables-ENR | tables-ENR |
Significant-point-reference | tables-ENR | tables-ENR | Significant-point-remark | tables-ENR | tables-ENR |
Significant-point-remark-reference | tables-ENR | tables-ENR | Sub-section | structure | structure |
Supplement | supplements | supplements | SUP-section | structure | structure |
Title | structure | structure | a | generic | inline |
br | generic | inline | caption | generic | table |
cite | generic | inline | col | generic | table |
colgroup | generic | table | div | block | block |
em | generic | inline | li | generic | lists |
ol | generic | lists | p | generic | block |
span | generic | inline | strong | generic | inline |
table | table | table | tbody | generic | table |
td | generic | table | tfoot | generic | table |
th | generic | table | thead | generic | table |
tr | generic | table | ul | generic | lists |
How to integrate your own templates with the provided ones? If you want to re-use most of the provided style sheets but need customisation for a few templates, you can avoid modifying the provided style sheets. Here is how:
Create your own XSLT file and write your templates (matching or named) in it;
In your XSLT file, import one of the provided main files (html-content.xslt, html-menu.xslt or fo-content.xslt), depending on your needs; by that way, your templates will override the imported ones;
In your templates, take care to call the right provided templates or to "apply-templates", where applicable, to make the link to other, provided templates;
Alternatively, if your templates allows it, use "apply-imports" to call the default processing for the node your template matches.
The objective of this section is to explain how the eAIP content logic is implemented, when it may see awkward.
The XSLT code which builds route tables in ENR 3.1 to ENR 3.5 was originally developed "by example", i.e. by closely following the ICAO AIP Specimen. This may seem too restrictive sometimes, but can be changed: These restrictions are only present in the XSLT transformations and not in the DTD. Specifically, the following rules are implemented:
Route-segment-width and Route-segment-COP are not considered for ENR-3.3 and 3.5
Route-segment-minimum and Route-segment-lower-override are not considered for 3.2, 3.3 and 3.5
The eAIP DTD features a class attribute on every elements, with the objective of separating presentation from content. When an element needs a specific styling, the editor gives a name to this styling and use it in the class attribute. This name is then used in HTML and XSL-FO transformations to look for the corresponding style definition.
For XHTML, the transformation is rather straightforward: the class name is simply copied to the XHTML file generated. The style definition are located in a CSS file named eAIP.css.
In XSL-FO, there is no way to define classes externally: all styling has to be defined as attributes on XSL-FO elements. So, our transformation converts class names to XSLT attribute-sets elements, which are applied to XSL-FO elements. Attribute-sets are defined in the file fo-styles.xslt.
However, a limitation of XSLT imposes that attribute-sets are used statically. That is, a transformation is supposed to know in advance the name of an attribute-set it uses. We sometimes have static attribute-sets, when we use the default class name for a given element. For example, an Address element is formatted using the Address attribute-set. Here is its presentation template (amendment processing removed for clarity):
<xsl:template name="AddressStyle">
<fo:block xsl:use-attribute-sets="Address">
<xsl:call-template name="AddressContent"/>
</fo:block>
</xsl:template>
But, when we need to convert the class name declared in a class attribute, this is of course not possible and we then need to apply an attribute-set dynamically. The following is illegal XSLT code:
<xsl:template name="AddressStyle">
<fo:block xsl:use-attribute-sets="Address {@class}"><!-- illegal -->
<xsl:call-template name="AddressContent"/>
</fo:block>
</xsl:template>
There are three known workarounds, as explained by Jeni Tennison in an email on the XSL-list mailing list titled "Re: [xsl] using variable as a value for "use-attribute-sets"". We have chosen the second solution, which basically consists in parsing our fo-styles.xslt file from within our transformation, just like any other XML file, and use it as our data source for class names to attribute-sets conversion. This trick is implemented in the file fo-att-set.xslt. We expanded Jeni Tennison's example so that variables and parameters are processed and attribute-sets can use other attribute-sets.
The following template, taken from fo-att-set.xslt, shows the generic handling of the class attribute:
<xsl:template match="@class">
<xsl:call-template name="use-att-set">
<xsl:with-param name="CLASS" select="string(.)"/>
</xsl:call-template>
</xsl:template>
Note that in most cases, this template is not actually used, because the value of the class attribute generally needs to be combined with other classes.
A class name is defined as follows in fo-styles.xslt:
<xsl:attribute-set name="region-common">
<xsl:attribute name="margin-top">1cm</xsl:attribute>
<xsl:attribute name="margin-bottom">1.5cm</xsl:attribute>
</xsl:attribute-set>
<xsl:variable name="outside-margin">1cm</xsl:variable>
<xsl:variable name="inside-margin">2cm</xsl:variable>
<xsl:attribute-set name="Left-region-body" use-attribute-sets="region-common">
<xsl:attribute name="margin-left"><xsl:value-of select="$outside-margin"/></xsl:attribute>
<xsl:attribute name="margin-right"><xsl:value-of select="$inside-margin"/></xsl:attribute>
</xsl:attribute-set>
The class Left-region-body is implemented by the attribute-set of the same name. This attribute-set uses another attribute-set, region-common, which sets more attributes, common to Left-region-body and others. Left-region-body's attributes make use of variables, also defined above.
There are some limitations in our implementations:
A variable or parameter must be defined by its content (as in the variable outside-margin, line 6 above), not by its select attribute, if it is called in an attribute inside an attribute-set that may be used dynamically;
In such a variable or parameter, only text nodes will be used; specifically, value-of elements will not be resolved (they are only resolved in an attribute, as in line 10 above).
It is possible to overcome these limitations, but we don't need it so far.