Apollo Transcripts: XSL Formatting Transformations
By Eric Hartwell - last updated
April 1, 2006

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> <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"><XmlTransform xslfile="C:/Domains/ehartwell.com/wwwroot/wiki/extensions/AS17Flight.xsl"></xsl:text>
<xsl:apply-templates />
<xsl:text disable-output-escaping="yes"><style type="text/css"></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"></style></xsl:text>
<xsl:text disable-output-escaping="yes"></XmlTransform></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"></XmlTransform></xsl:text>
==<xsl:value-of select="@chapter" /><xsl:if test="@chapter">: </xsl:if><xsl:value-of
select="@title" />==
<xsl:text disable-output-escaping="yes"><XmlTransform xslfile="C:/Domains/ehartwell.com/wwwroot/wiki/extensions/AS17Flight.xsl"></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"></XmlTransform></xsl:text>
{{:<xsl:value-of select="@title" />}}
<xsl:text disable-output-escaping="yes"><XmlTransform xslfile="C:/Domains/ehartwell.com/wwwroot/wiki/extensions/AS17Flight.xsl"></xsl:text>
</xsl:template>
<xsl:template match="event/include">
<xsl:text disable-output-escaping="yes"></event></XmlTransform></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"><XmlTransform xslfile="C:/Domains/ehartwell.com/wwwroot/wiki/extensions/AS17Flight.xsl"><event></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