Apollo transcripts: XSL formatting transformations

InfoDabble > Tech Notes > AFJ > Apollo transcripts: XSL formatting transformations
Jump to: navigation, search

By Eric Hartwell - last updated last updated April 1, 2006

Note: The Apollo 17 Flight Journal now uses extended wikitext instead of this pure XML format.

For the Apollo 17 project I decided to use a generic and extensible XML format for the timeline data instead of hard-coding the HTML. The formatting can easily be applied using an XSLT style sheet.

Given the XML data layout and the desired HTML output format, designing the XSLT is fairly straightforward.

Required Space

XSLT drops spaces between tags, but does not support   Many sources recommend using   as a replacement, but MediaWiki rejects this. It turns out the HTML standard does not support ASCII characters higher than #FF.

For the time being, I rearranged the style sheet so that there is always a non-blank character adjacent to a required space.

  • Not allowed: <b>Cernan:</b>&nbsp;'<xsl:value-of select="node()" />
  • Workaround: <b>Cernan: </b><xsl:value-of select="node()" />


First Pass

The first pass translates tags that will be rendered by wikitext, adds the transcript-specific style sheet, and wraps the remaining tags with XmlTransform instructions for the second pass.

Tag Attribute Action Output Format
/ (root) Insert or append transcript's CSS styles
Wrap output with <XmlTransform xsl="xsl2"> ... </XmlTransform>
<XmlTransform xsl="xsl2">
....
<style type="text/css"> ... </style>
</XmlTransform>
section Tag as ==Wikitext heading 2== </XmlTransform>
==value of chapter attribute: value of title attribute==
<XmlTransform xsl="xsl2">
chapter (optional) Prefixed to title as Chapter: Title
title Title of section
seq (optional) Sequence and/or section number
include Insert content from a wikitext page {{Wikitext template}} </XmlTransform>
{{value of title attribute}}
<XmlTransform xsl="xsl2">
title Title of wikitext page to insert
Note: Should use a lookup table to convert the transcript's section title to the title of the corresponding wiki page.
event/include Insert content from a wikitext page {{Wikitext template}} </event></XmlTransform>
{{value of title attribute}}
<XmlTransform xsl="xsl2"><event>
title Title of wikitext page to insert
Future tags
photo Insert image from a wikitext page {{Wikitext template}} </event></XmlTransform>
(wikitext image reference)
<XmlTransform xsl="xsl2"><event>

The actual Apollo 17 first pass transcript XSL looks like this:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" />
 
<!-- Main transform with style sheet at end -->
 
<xsl:template match="/">
<xsl:text disable-output-escaping="yes">&lt;XmlTransform xslfile="C:/Domains/ehartwell.com/wwwroot/wiki/extensions/AS17Flight.xsl"&gt;</xsl:text>
 
<xsl:apply-templates />
 
<xsl:text disable-output-escaping="yes">&lt;style type="text/css"&gt;</xsl:text>
.met {font-family: Arial, Helvetica, sans-serif; font-size: 12px; color: black}
.def {font-family: Arial, Helvetica, sans-serif; font-size: 12px; color: black}
.pao {font-family: Arial, Helvetica, sans-serif; font-size: 12px; color: DarkGreen; margin-left:25px}
.ob {font-family: Arial, Helvetica, sans-serif; font-size: 12px; color: #660000; margin-left:25px}
.tec {font-family: Arial, Helvetica, sans-serif; font-size: 12px; color: black; margin-left:25px}
.ed {font-family: Arial, Helvetica, sans-serif; font-size: 12px; color: Blue; margin-left:50px}
.edinc {font-family: Arial, Helvetica, sans-serif; font-size: 12px; color: MediumBlue; margin-left:60px; margin-right:50px;}
.db {font-family: Arial, Helvetica, sans-serif; font-size: 12px; color: SaddleBrown; margin-left:50px}
.alt {font-family: Arial, Helvetica, sans-serif; font-size: 11px; color: DimGray; margin-left:40px; margin-top:-10px;}
.other {font-family: Arial, Helvetica, sans-serif; font-size: 12px; color: black; margin-left:25px}
.photo {font-family: Arial, Helvetica, sans-serif; font-size: 12px; color: red; margin-left:25px}
<xsl:text disable-output-escaping="yes">&lt;/style&gt;</xsl:text>
<xsl:text disable-output-escaping="yes">&lt;/XmlTransform&gt;</xsl:text>
</xsl:template>
 
<xsl:template match="XmlTransformInput">
<xsl:apply-templates />
</xsl:template>
 
<!-- Section titles -->
 
<xsl:template match="section">
<xsl:text disable-output-escaping="yes">&lt;/XmlTransform&gt;</xsl:text>
==<xsl:value-of select="@chapter" /><xsl:if test="@chapter">: </xsl:if><xsl:value-of select="@title" />==
<xsl:text disable-output-escaping="yes">&lt;XmlTransform xslfile="C:/Domains/ehartwell.com/wwwroot/wiki/extensions/AS17Flight.xsl"&gt;</xsl:text>
<xsl:apply-templates />
</xsl:template>
 
<!-- Include a wiki page: Root level and part of an event -->
 
<xsl:template match="/include">
<xsl:text disable-output-escaping="yes">&lt;/XmlTransform&gt;</xsl:text>
{{:<xsl:value-of select="@title" />}}
<xsl:text disable-output-escaping="yes">&lt;XmlTransform xslfile="C:/Domains/ehartwell.com/wwwroot/wiki/extensions/AS17Flight.xsl"&gt;</xsl:text>
</xsl:template>
 
<xsl:template match="event/include">
<xsl:text disable-output-escaping="yes">&lt;/event&gt;&lt;/XmlTransform&gt;</xsl:text>
<div class="edinc"><p><b>[[<xsl:value-of select="@title" />]]: </b>{{:<xsl:value-of select="@title" />}}</p></div>
<xsl:text disable-output-escaping="yes">&lt;XmlTransform xslfile="C:/Domains/ehartwell.com/wwwroot/wiki/extensions/AS17Flight.xsl"&gt;&lt;event&gt;</xsl:text>
</xsl:template>
 
<!-- Important! Preserve all XML tags that we don't explicitly process here -->
 
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
 
</xsl:stylesheet>

Second Pass

The second pass processes the content tags that weren't handled in the first pass. Most of the HTML formatting is done here because the tags would have been stripped by the wikitext parser in the previous pass.

The actual Apollo 17 second pass transcript XSL looks like this:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" />
 
<xsl:template match="/">
<xsl:apply-templates />
</xsl:template>
 
<xsl:template match="section">
<xsl:apply-templates />
</xsl:template>
<xsl:template match="subsection">
<xsl:apply-templates />
</xsl:template>
 
<xsl:template match="event">
<p class="met"><b><xsl:value-of select="@met" /></b></p>
<xsl:apply-templates />
</xsl:template>
 
<xsl:template match="event/quote[@src='TechDebrief']">
<xsl:choose > 
<xsl:when test = "@who='CDR'"><p class="db"><b>Cernan</b> (Technical Debriefing) <xsl:value-of select="node()" /></p></xsl:when> 
<xsl:when test = "@who='CMP'"><p class="db"><b>Evans</b> (Technical Debriefing) <xsl:value-of select="node()" /></p></xsl:when> 
<xsl:when test = "@who='LMP'"><p class="db"><b>Schmitt</b> (Technical Debriefing) <xsl:value-of select="node()" /></p></xsl:when> 
<xsl:otherwise><p class="db"><b><xsl:value-of select="@who" /></b> (Technical Debriefing) <xsl:value-of select="node()" /></p></xsl:otherwise>
</xsl:choose> 
</xsl:template>
 
<xsl:template match="event/quote[not(@src)]">
<xsl:choose > 
<xsl:when test = "@who='CDR'"><p class="tec"><b>Cernan: </b><xsl:value-of select="node()" /></p></xsl:when> 
<xsl:when test = "@who='CMP'"><p class="tec"><b>Evans: </b><xsl:value-of select="node()" /></p></xsl:when> 
<xsl:when test = "@who='LMP'"><p class="tec"><b>Schmitt: </b><xsl:value-of select="node()" /></p></xsl:when> 
<xsl:when test = "@who='CCo'"><p class="tec"><b>Obermeyer: </b><xsl:value-of select="node()" /></p></xsl:when> 
<xsl:when test = "@who='CCp'"><p class="tec"><b>Parker: </b><xsl:value-of select="node()" /></p></xsl:when> 
<xsl:when test = "@who='PAO'"><p class="pao"><b>Public Affairs Officer: </b><xsl:value-of select="node()" /></p></xsl:when> 
<xsl:when test = "@who='LCC'"><p class="pao"><b>Launch Control: </b><xsl:value-of select="node()" /></p></xsl:when> 
<xsl:otherwise><p class="other"><b><xsl:value-of select="@who" />: </b><xsl:value-of select="node()" /></p></xsl:otherwise>
</xsl:choose> 
<xsl:apply-templates select="alternate" />
</xsl:template>
 
<xsl:template match="event/quote/alternate">
<p class="alt">
<xsl:choose > 
<xsl:when test = "@src='PAO'">(PAO) </xsl:when> 
<xsl:when test = "@src='Tech'">(Air-to-Ground) </xsl:when> 
<xsl:otherwise>(Tape 17-<xsl:value-of select="@src" />) </xsl:otherwise>
</xsl:choose>
<xsl:value-of select="node()" /><br /> 
</p>
</xsl:template>
 
<xsl:template match="event/photo">
<p class="photo"><b>Photo <xsl:value-of select="@id" /></b>
<xsl:if test = "@frame"> (Frame <xsl:value-of select="@frame" />) </xsl:if>
<xsl:if test = "node()"> <b>:</b><xsl:value-of select="node()" /></xsl:if>
</p>
</xsl:template>
 
<xsl:template match="event/comment">
<p class="ed">[<xsl:value-of select="node()" />]</p>
</xsl:template>
 
<xsl:template match="style">
<style type="text/css"><xsl:value-of select="node()" /></style>
</xsl:template>
 
</xsl:stylesheet>

Revision History

  • April 1, 2006 - two-pass transform
  • March 27, 2006 - initial version