TEI stylesheet for making Word docx files from TEI XML
This software is dual-licensed:
1. Distributed under a Creative Commons Attribution-ShareAlike 3.0
Unported License http://creativecommons.org/licenses/by-sa/3.0/
2. http://www.opensource.org/licenses/BSD-2-Clause
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
This software is provided by the copyright holders and contributors
"as is" and any express or implied warranties, including, but not
limited to, the implied warranties of merchantability and fitness for
a particular purpose are disclaimed. In no event shall the copyright
holder or contributors be liable for any direct, indirect, incidental,
special, exemplary, or consequential damages (including, but not
limited to, procurement of substitute goods or services; loss of use,
data, or profits; or business interruption) however caused and on any
theory of liability, whether in contract, strict liability, or tort
(including negligence or otherwise) arising in any way out of the use
of this software, even if advised of the possibility of such damage.
Before main processing starts, pre-process the document
elements in a separate mode ('pass0'), in order to add extra
material which implements the footnoting etc. Also check that
old files are there to be read.
<xsl:template name="create-document-dot-xml"><w:document><w:body><!-- Front --><xsl:call-template name="write-document-dot-xml-frontmatter"/><!-- Main --><xsl:call-template name="write-document-dot-xml-maincontent"/><!-- Back --><xsl:call-template name="write-document-dot-xml-backmatter"/><!-- Clearing up at the end --><xsl:call-template name="write-document-dot-xml-postclearing"/></w:body></w:document></xsl:template>
<xsl:template name="write-document-dot-xml-frontmatter"><!-- are there specific titlepages --><xsl:call-template name="titlepages"/><!-- The front matter --><xsl:apply-templates select=".//tei:text/tei:front"/></xsl:template>
<xsl:template name="write-document-dot-xml-maincontent"><!-- document title --><xsl:call-template name="document-title"/><!-- header components --><xsl:call-template name="headerParts"/><!-- Describes the main part of the document --><xsl:apply-templates select=".//tei:text/tei:body"/></xsl:template>
<xsl:template name="write-document-dot-xml-backmatter"><!-- Describes the back matter of the document --><xsl:apply-templates select=".//tei:text/tei:back"/></xsl:template>
<xsl:template name="write-document-dot-xml-postclearing"><!-- write out final sectPr .. if exists --><xsl:choose><xsl:when test="tei:text/tei:milestone"><xsl:apply-templates select="tei:text/tei:milestone[1]"><xsl:with-param name="final-section">true</xsl:with-param></xsl:apply-templates></xsl:when><xsl:otherwise><xsl:apply-templates select="doc($defaultHeaderFooterFile)/tei:TEI/tei:text/tei:milestone"><xsl:with-param name="final-section">true</xsl:with-param></xsl:apply-templates></xsl:otherwise></xsl:choose></xsl:template>
This template processes block elements (or better to say the children of a block element)
and should never be called directly (call block-element instead). The function processes
all children and puts
all inline elements into one w:p. If it encounters a nested block element
(e.g. a note inside a p) then it closes the previous w:p processes that block
element and then again starts putting all following inline elements into another
w:p element.
@see block-element
<xsl:template name="_process-blockelement"><xsl:param name="style"/><xsl:param name="pPr" as="node()*"/><xsl:param name="nop"/><xsl:param name="bookmark-id"/><xsl:param name="bookmark-name"/><!-- Process Child elements --><xsl:for-each-group select="current-group()" group-starting-with="*[not(tei:isInline(.))]"><xsl:choose><!-- if the current item is a block element, we process that one,
and then call this function recursively over all the other
elements --><xsl:when test="self::*[not(tei:isInline(.))]"><!-- process block element --><xsl:apply-templates select="."><xsl:with-param name="style" select="$style"/><xsl:with-param name="pPr" select="$pPr" as="node()*"/><xsl:with-param name="nop" select="$nop"/></xsl:apply-templates><!-- process all the other elements in the current group --><xsl:for-each-group select="current-group() except ." group-adjacent="1"><xsl:call-template name="_process-blockelement"><xsl:with-param name="style" select="$style"/><xsl:with-param name="pPr" select="$pPr" as="node()*"/><xsl:with-param name="nop" select="$nop"/></xsl:call-template></xsl:for-each-group></xsl:when><!-- we encountered an inline element. This means that the current group only
contains inline elements --><xsl:otherwise><!-- create all text runs for each item in the current group. we will later
on decide whether we are grouping them together in a w:p or not. --><xsl:variable name="innerRuns"><!-- add paragraph properties (if nobody else created a w:p ($nop)) --><xsl:if test="$nop!='true'"><xsl:choose><xsl:when test="not($style='')"><w:pPr><w:pStyle><xsl:attribute name="w:val" select="$style"/></w:pStyle></w:pPr><xsl:copy-of select="$pPr[not(self::w:pPr)]"/></xsl:when><xsl:when test="not(empty($pPr))"><xsl:copy-of select="$pPr"/></xsl:when></xsl:choose></xsl:if><!-- bookmark start --><xsl:if test="string-length($bookmark-name) > 0 and string-length($bookmark-id) > 0"><w:bookmarkStart w:id="{$bookmark-id}" w:name="{$bookmark-name}"/></xsl:if><!-- Create text runs --><xsl:for-each select="current-group()"><xsl:apply-templates select="."><xsl:with-param name="style" select="$style"/><xsl:with-param name="pPr" select="$pPr" as="node()*"/></xsl:apply-templates></xsl:for-each><!-- bookmark end--><xsl:if test="string-length($bookmark-name) > 0 and string-length($bookmark-id) > 0"><w:bookmarkEnd w:id="{$bookmark-id}"/></xsl:if></xsl:variable><!-- write out text runs.
if someone has already created a w:p ($nop) we may not create another one. --><xsl:choose><xsl:when test="$nop='true'"><xsl:copy-of select="$innerRuns"/></xsl:when><xsl:otherwise><w:p><xsl:copy-of select="$innerRuns"/></w:p></xsl:otherwise></xsl:choose></xsl:otherwise></xsl:choose></xsl:for-each-group><!-- end process children --></xsl:template>
Tests whether to add rendering elements to a run.
Word styles cannot not be added in applyRend. If you want to add
a style go for a get-style template. The order of these
elements in Word does matter, by the way.
Template
tei:head[parent::tei:div or parent::tei:div1 or parent::tei:div2 or parent::tei:div3
or parent::tei:div4 or parent::tei:div5 or parent::tei:div6 or parent::tei:div7]
Documentation
Description
Headers and Sections
Namespace
No namespace
Match
tei:head[parent::tei:div or parent::tei:div1 or parent::tei:div2 or parent::tei:div3
or parent::tei:div4 or parent::tei:div5 or parent::tei:div6 or parent::tei:div7]
<xsl:template match="tei:cell"><w:tc><xsl:choose><xsl:when test="w:tcPr"><xsl:copy-of select="w:tcPr"/></xsl:when><xsl:otherwise><w:tcPr><!--w:tcW w:w="1915" w:type="dxa"/--><xsl:if test="@cols"><w:gridSpan w:val="{@cols}"/></xsl:if></w:tcPr></xsl:otherwise></xsl:choose><xsl:choose><xsl:when test="not(text()) and count(*)=1 and not(tei:isInline(*))"><xsl:apply-templates/></xsl:when><xsl:otherwise><xsl:call-template name="block-element"><xsl:with-param name="pPr" as="node()*"><w:pPr><xsl:choose><xsl:when test="@rend"><xsl:variable name="sName"><xsl:call-template name="getStyleName"><xsl:with-param name="in" select="@rend"/></xsl:call-template></xsl:variable><xsl:choose><xsl:when test="$sName=''"><w:pStyle w:val="{$TableText}"/></xsl:when><xsl:otherwise><w:pStyle w:val="{$sName}"/></xsl:otherwise></xsl:choose></xsl:when><xsl:otherwise><w:pStyle w:val="{$TableText}"/></xsl:otherwise></xsl:choose><xsl:choose><xsl:when test="@teidocx:align"><w:jc w:val="{@teidocx:align}"/></xsl:when><xsl:when test="parent::tei:row[@role='label'] or @role='label'"><w:jc w:val="left"/></xsl:when><xsl:when test="starts-with(.,'[0-9]')"><w:jc w:val="right"/></xsl:when><xsl:otherwise><w:jc w:val="left"/></xsl:otherwise></xsl:choose></w:pPr></xsl:with-param></xsl:call-template></xsl:otherwise></xsl:choose><!-- If we have no children, put an empty p here --><xsl:if test="not(descendant::text())"><w:p><w:pPr><w:pStyle w:val="Tabletext9"/></w:pPr><w:r><w:t/></w:r></w:p></xsl:if></w:tc></xsl:template>
<xsl:template match="cals:entry" mode="contents"><xsl:call-template name="block-element"><xsl:with-param name="pPr" as="node()*"><w:pPr><xsl:choose><xsl:when test="@rend"><xsl:variable name="sName"><xsl:call-template name="getStyleName"><xsl:with-param name="in" select="@rend"/></xsl:call-template></xsl:variable><xsl:choose><xsl:when test="$sName=''"><w:pStyle w:val="{$TableText}"/></xsl:when><xsl:otherwise><w:pStyle w:val="{$sName}"/></xsl:otherwise></xsl:choose></xsl:when><xsl:otherwise><w:pStyle w:val="{$TableText}"/></xsl:otherwise></xsl:choose><xsl:choose><xsl:when test="@align"><w:jc w:val="{@align}"/></xsl:when><xsl:when test="parent::tei:row[@role='label'] or @role='label'"><w:jc w:val="left"/></xsl:when><xsl:when test="starts-with(.,'[0-9]')"><w:jc w:val="right"/></xsl:when><xsl:otherwise><w:jc w:val="left"/></xsl:otherwise></xsl:choose></w:pPr></xsl:with-param><xsl:with-param name="nop"><xsl:choose><xsl:when test="not(text()) and tei:note[(not(@place))]">true</xsl:when><!--NEN: next when commented to make footnotes in table possible--><!--<xsl:when test="not(text()) and tei:note[@place='foot']">true</xsl:when>--><xsl:otherwise>false</xsl:otherwise></xsl:choose></xsl:with-param></xsl:call-template><!-- If we have no children, put an empty p here --><xsl:choose><xsl:when test="*"/><xsl:when test="text()"/><xsl:otherwise><w:p><w:pPr><w:pStyle w:val="Tabletext9"/></w:pPr><w:r><w:t/></w:r></w:p></xsl:otherwise></xsl:choose></xsl:template>
<xsl:template name="marginalNote"><xsl:call-template name="block-element"><xsl:with-param name="style"><xsl:value-of select="if (@place='margin') then 'marginOuter' else if (starts-with(@place,'margin-')) then concat('margin',upper-case(substring(@place,8,1)),substring(@place,9)) else @place"/></xsl:with-param></xsl:call-template></xsl:template>
<xsl:template name="makeBlock"><xsl:param name="style"/><xsl:call-template name="block-element"><xsl:with-param name="style"><xsl:value-of select="if ($style='docAuthor') then 'Author' else if ($style='docTitle') then 'Title' else if ($style='titlePart') then 'Title' else $style"/></xsl:with-param></xsl:call-template></xsl:template>
A4 is 210mm x 297mm; leaving 1in margin (25mm),
gives 160 x 247 approx useable area. For figures,
Microsoft use English metrical units (emu), in which
1mm = 3600 units. So page size is 57600 * 889200
Divide by 100 to avoid overflow in calculations.
For other measurements in Word, see useful discussion at
http://startbigthinksmall.wordpress.com/2010/01/04/points-inches-and-emus-measuring-units-in-office-open-xml/