TEI stylesheet for merging TEI ODD specification with source to
make a new source document.
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.
<xsl:template match="tei:schemaSpec" mode="pass1"><xsl:variable name="pass1"><xsl:copy><xsl:copy-of select="@*"/><xsl:sequence select="if ($verbose='true')then tei:message(concat('Schema pass 1: ',@ident)) else ()"/><!--
it is important to process "tei" and "core" first
because of the order of declarations
--><xsl:for-each select="tei:moduleRef[@key eq 'tei']"><xsl:call-template name="odd2odd-expandModule"/></xsl:for-each><xsl:for-each select="tei:moduleRef[@key eq 'core']"><xsl:call-template name="odd2odd-expandModule"/></xsl:for-each><xsl:for-each select="tei:moduleRef[@key]"><xsl:if test="not(@key eq 'tei' or @key eq 'core')"><xsl:call-template name="odd2odd-expandModule"/></xsl:if></xsl:for-each><xsl:for-each select="*[not(self::tei:moduleRef[@key])]"><xsl:apply-templates select="." mode="pass1"/></xsl:for-each></xsl:copy></xsl:variable><!--
<xsl:result-document href="/tmp/odd2odd-pass1.xml">
<xsl:copy-of select="$pass1"/>
</xsl:result-document>
--><xsl:for-each select="$pass1"><xsl:apply-templates mode="pass2"/></xsl:for-each></xsl:template>
<xsl:template name="odd2odd-checkObject"><!--
for every object
- if its in the ODD spec's REPLACE list, use that
- if its in ODD spec's CHANGE list (do the hard merge bit)
- if its duplicated by an existing spec, ignore
- otherwise copy
done
--><xsl:variable name="specName" select="tei:uniqueName(.)"/><xsl:variable name="N" select="local-name(.)"/><xsl:choose><xsl:when test="$ODD/key('odd2odd-DELETE',$specName)"><xsl:if test="$verbose='true'"><xsl:message>Phase 2: delete<xsl:value-of select="$specName"/></xsl:message></xsl:if></xsl:when><xsl:when test="$ODD/key('odd2odd-REPLACE',$specName)"><xsl:if test="$verbose='true'"><xsl:message>Phase 2: replace<xsl:value-of select="$specName"/></xsl:message></xsl:if><xsl:apply-templates mode="odd2odd-copy" select="$ODD/key('odd2odd-REPLACE',$specName)"/></xsl:when><xsl:when test="$ODD/key('odd2odd-CHANGE',$specName)"><xsl:if test="$verbose='true'"><xsl:message>Phase 2: change<xsl:value-of select="$specName"/></xsl:message></xsl:if><xsl:apply-templates mode="odd2odd-change" select="."/></xsl:when><xsl:otherwise><xsl:if test="$verbose='true'"><xsl:message>Phase 2: keep<xsl:value-of select="($N,$specName)"/></xsl:message></xsl:if><xsl:apply-templates mode="justcopy" select="."/></xsl:otherwise></xsl:choose></xsl:template>
<xsl:template match="tei:dataSpec|tei:macroSpec" mode="odd2odd-change"><xsl:variable name="specName" select="tei:uniqueName(.)"/><xsl:variable name="ORIGINAL" select="."/><xsl:copy><xsl:attribute name="rend">change</xsl:attribute><xsl:apply-templates mode="odd2odd-change" select="@*"/><!--
For each macro, go through most of the sections one by one
and see if they are present in the change mode version.
If so, use them as is.
--><xsl:for-each select="$ODD"><xsl:for-each select="key('odd2odd-CHANGE',$specName)"><!-- if there is an altIdent, use it --><xsl:apply-templates mode="justcopy" select="tei:altIdent"/><!-- equiv, gloss, desc trio --><xsl:choose><xsl:when test="$stripped='true'"/><xsl:when test="tei:equiv"><xsl:apply-templates mode="justcopy" select="tei:equiv"><xsl:with-param name="rend">replace</xsl:with-param></xsl:apply-templates></xsl:when><xsl:otherwise><xsl:apply-templates mode="odd2odd-copy" select="$ORIGINAL/tei:equiv"/></xsl:otherwise></xsl:choose><xsl:choose><xsl:when test="tei:gloss"><xsl:apply-templates mode="justcopy" select="tei:gloss"><xsl:with-param name="rend">replace</xsl:with-param></xsl:apply-templates></xsl:when><xsl:otherwise><xsl:apply-templates mode="justcopy" select="$ORIGINAL/tei:gloss"/></xsl:otherwise></xsl:choose><xsl:choose><xsl:when test="$stripped='true'"/><xsl:when test="tei:desc"><xsl:apply-templates mode="justcopy" select="tei:desc"><xsl:with-param name="rend">replace</xsl:with-param></xsl:apply-templates></xsl:when><xsl:otherwise><xsl:apply-templates mode="justcopy" select="$ORIGINAL/tei:desc"/></xsl:otherwise></xsl:choose><!-- content --><xsl:choose><xsl:when test="tei:dataRef"><xsl:apply-templates mode="justcopy" select="tei:dataRef"><xsl:with-param name="rend">replace</xsl:with-param></xsl:apply-templates></xsl:when><xsl:when test="tei:content"><xsl:apply-templates mode="justcopy" select="tei:content"><xsl:with-param name="rend">replace</xsl:with-param></xsl:apply-templates></xsl:when><xsl:when test="$ORIGINAL/tei:dataRef"><xsl:apply-templates mode="odd2odd-copy" select="$ORIGINAL/tei:dataRef"><xsl:with-param name="rend">replace</xsl:with-param></xsl:apply-templates></xsl:when><xsl:otherwise><xsl:apply-templates mode="odd2odd-copy" select="$ORIGINAL/tei:content"/></xsl:otherwise></xsl:choose><xsl:choose><xsl:when test="tei:valList"><xsl:apply-templates mode="justcopy" select="tei:valList[1]"><xsl:with-param name="rend">replace</xsl:with-param></xsl:apply-templates></xsl:when><xsl:when test="tei:stringVal"><xsl:apply-templates mode="justcopy" select="tei:stringVal"/></xsl:when><xsl:otherwise><xsl:apply-templates mode="odd2odd-copy" select="$ORIGINAL/tei:stringVal"/></xsl:otherwise></xsl:choose><!-- constraints --><xsl:call-template name="odd2odd-processConstraints"><xsl:with-param name="ORIGINAL" select="$ORIGINAL"/><xsl:with-param name="elementName" select="$specName"/></xsl:call-template><!-- exemplum, remarks and listRef are either replacements or not --><xsl:choose><xsl:when test="$stripped='true'"/><xsl:when test="tei:exemplum"><xsl:apply-templates mode="justcopy" select="tei:exemplum"/></xsl:when><xsl:otherwise><xsl:apply-templates mode="justcopy" select="$ORIGINAL/tei:exemplum"/></xsl:otherwise></xsl:choose><xsl:choose><xsl:when test="tei:remarks"><xsl:apply-templates mode="justcopy" select="tei:remarks"/></xsl:when><xsl:otherwise><xsl:apply-templates mode="justcopy" select="$ORIGINAL/tei:remarks"/></xsl:otherwise></xsl:choose><xsl:choose><xsl:when test="$stripped='true'"/><xsl:when test="tei:listRef"><xsl:apply-templates mode="justcopy" select="tei:listRef"/></xsl:when><xsl:otherwise><xsl:apply-templates mode="justcopy" select="$ORIGINAL/tei:listRef"/></xsl:otherwise></xsl:choose></xsl:for-each></xsl:for-each></xsl:copy></xsl:template>
<xsl:template match="tei:classSpec" mode="odd2odd-change"><xsl:variable name="className" select="tei:uniqueName(.)"/><xsl:variable name="ORIGINAL" select="."/><xsl:copy><xsl:attribute name="rend">change</xsl:attribute><xsl:apply-templates mode="odd2odd-change" select="@*"/><!-- for each section of the class spec,
go through the sections one by one
and see if they are present in the change mode version --><xsl:for-each select="$ODD"><xsl:for-each select="key('odd2odd-CHANGE',$className)"><!-- context is now a classSpec in change mode in the ODD spec --><!-- description --><!-- For each non-identifiable element type (namely:
<gloss>, <altIdent>, <equiv>, <desc>, then <remarks>,
<exemplum>, and <listRef>) copy instances over from the
customization ODD if it is present there, and from the
original source ODD if it is not present in the context
node; unless we are stripping out prose content stuff,
in which case some are not copied no matter what. The
<classes>, <constraintSpec>s, and <attList> are handled
differently, as they are identifiable. --><xsl:choose><!-- maybe copy <gloss>s from ODD or ORIGINAL --><xsl:when test="$stripped='true'"/><xsl:when test="tei:gloss"><xsl:apply-templates mode="justcopy" select="tei:gloss"/></xsl:when><xsl:otherwise><xsl:apply-templates mode="justcopy" select="$ORIGINAL/tei:gloss"/></xsl:otherwise></xsl:choose><xsl:choose><!-- copy <altIdent>s from ODD or ORIGINAL --><xsl:when test="tei:altIdent"><xsl:apply-templates mode="justcopy" select="tei:altIdent"/></xsl:when><xsl:otherwise><xsl:apply-templates mode="justcopy" select="$ORIGINAL/tei:altIdent"/></xsl:otherwise></xsl:choose><xsl:choose><!-- copy <equiv>s from ODD or ORIGINAL --><xsl:when test="tei:equiv"><xsl:apply-templates mode="justcopy" select="tei:equiv"/></xsl:when><xsl:otherwise><xsl:apply-templates mode="justcopy" select="$ORIGINAL/tei:equiv"/></xsl:otherwise></xsl:choose><xsl:choose><!-- maybe copy <desc>s from ODD or ORIGINAL --><xsl:when test="$stripped='true'"/><xsl:when test="tei:desc"><xsl:apply-templates mode="justcopy" select="tei:desc"/></xsl:when><xsl:otherwise><xsl:apply-templates mode="justcopy" select="$ORIGINAL/tei:desc"/></xsl:otherwise></xsl:choose><!-- classes --><classes xmlns="http://www.tei-c.org/ns/1.0"><xsl:choose><xsl:when test="tei:classes[@mode eq 'change']"><xsl:for-each select="tei:classes/tei:memberOf"><xsl:choose><xsl:when test="@mode eq 'delete'"/><xsl:when test="@mode eq 'add' or not (@mode)"><memberOf key="{@key}"><xsl:copy-of select="@min|@max"/></memberOf></xsl:when></xsl:choose></xsl:for-each><xsl:for-each select="$ORIGINAL"><xsl:for-each select="tei:classes/tei:memberOf"><xsl:variable name="me"><xsl:value-of select="@key"/></xsl:variable><xsl:variable name="metoo"><xsl:value-of select="concat(../../@ident,@key)"/></xsl:variable><xsl:choose><xsl:when test="$ODD/key('odd2odd-DELETE',$me)"></xsl:when><xsl:when test="$ODD/key('odd2odd-MEMBEROFDELETE',$metoo)"></xsl:when><xsl:when test="$ODD/key('odd2odd-MEMBEROFADD',$metoo)"></xsl:when><xsl:otherwise><memberOf key="{$me}"/></xsl:otherwise></xsl:choose></xsl:for-each></xsl:for-each></xsl:when><xsl:when test="tei:classes"><xsl:for-each select="tei:classes/tei:memberOf"><xsl:copy-of select="."/></xsl:for-each></xsl:when><xsl:otherwise><xsl:for-each select="$ORIGINAL"><xsl:for-each select="tei:classes/tei:memberOf"><xsl:variable name="me"><xsl:value-of select="@key"/></xsl:variable><xsl:for-each select="$ODD"><xsl:if test="not(key('odd2odd-DELETE',$me))"><memberOf key="{$me}"/></xsl:if></xsl:for-each></xsl:for-each></xsl:for-each></xsl:otherwise></xsl:choose></classes><!-- constraints --><xsl:call-template name="odd2odd-processConstraints"><xsl:with-param name="ORIGINAL" select="$ORIGINAL"/><xsl:with-param name="elementName" select="$className"/></xsl:call-template><!-- attList --><xsl:if test="$ORIGINAL/tei:attList"><attList xmlns="http://www.tei-c.org/ns/1.0"><xsl:call-template name="odd2odd-processAttributes"><xsl:with-param name="ORIGINAL" select="$ORIGINAL"/><xsl:with-param name="objectName" select="$className"/></xsl:call-template></attList></xsl:if><xsl:choose><!-- maybe copy <exemplum>s from ODD or ORIGINAL --><xsl:when test="$stripped='true'"/><xsl:when test="tei:exemplum"><xsl:apply-templates mode="justcopy" select="tei:exemplum"/></xsl:when><xsl:otherwise><xsl:apply-templates mode="justcopy" select="$ORIGINAL/tei:exemplum"/></xsl:otherwise></xsl:choose><xsl:choose><!-- maybe copy <remarks>s from ODD or ORIGINAL --><xsl:when test="$stripped='true'"/><xsl:when test="tei:remarks"><xsl:apply-templates mode="justcopy" select="tei:remarks"/></xsl:when><xsl:otherwise><xsl:apply-templates mode="justcopy" select="$ORIGINAL/tei:remarks"/></xsl:otherwise></xsl:choose><xsl:choose><!-- maybe copy <listRef>s from ODD or ORIGINAL --><xsl:when test="$stripped='true'"/><xsl:when test="tei:listRef"><xsl:apply-templates mode="justcopy" select="tei:listRef"/></xsl:when><xsl:otherwise><xsl:apply-templates mode="justcopy" select="$ORIGINAL/tei:listRef"/></xsl:otherwise></xsl:choose></xsl:for-each></xsl:for-each></xsl:copy></xsl:template>
<xsl:template name="odd2odd-simplifyRelax"><xsl:variable name="element"><xsl:value-of select="local-name(.)"/></xsl:variable><!--
for each RELAX NG content model,
remove reference to any elements which have been
deleted, or to classes which are empty.
This may make the container empty,
so that is only put back in if there is some content
--><xsl:variable name="contents"><WHAT><xsl:for-each select="a:*|rng:*|processing-instruction()"><xsl:choose><xsl:when test="self::a:*"><xsl:copy-of select="."/></xsl:when><xsl:when test="self::processing-instruction()"><xsl:copy-of select="."/></xsl:when><xsl:when test="self::rng:element | self::rng:name | self::rng:attribute | self::rng:data | self::rng:text "><xsl:copy><xsl:copy-of select="@*"/><xsl:apply-templates mode="odd2odd-copy"/></xsl:copy></xsl:when><xsl:when test="self::rng:value"><value xmlns="http://relaxng.org/ns/structure/1.0"><xsl:apply-templates/></value></xsl:when><xsl:when test="self::rng:ref"><xsl:variable name="N" select="@name"/><xsl:for-each select="$ODD"><xsl:choose><xsl:when test="$stripped='true'"><ref xmlns="http://relaxng.org/ns/structure/1.0" name="{$N}"/></xsl:when><xsl:when test="key('odd2odd-DELETE',$N)"/><xsl:otherwise><ref xmlns="http://relaxng.org/ns/structure/1.0" name="{$N}"/></xsl:otherwise></xsl:choose></xsl:for-each></xsl:when><xsl:otherwise><xsl:call-template name="odd2odd-simplifyRelax"/></xsl:otherwise></xsl:choose></xsl:for-each></WHAT></xsl:variable><xsl:variable name="entCount"><xsl:value-of select="count($contents/WHAT/*)"/></xsl:variable><xsl:for-each select="$contents/WHAT"><xsl:choose><xsl:when test="$entCount=1 and local-name(*)=$element"><xsl:copy-of select="@*|*|text()|processing-instruction()"/></xsl:when><xsl:when test="$element='optional' and $entCount=1 and rng:zeroOrMore"><xsl:copy-of select="@*|*|text()|processing-instruction()"/></xsl:when><xsl:when test="$element='optional' and $entCount=1 and rng:oneOrMore"><xsl:copy-of select="@*|*|text()|processing-instruction()"/></xsl:when><xsl:when test="$element='oneOrMore' and $entCount=1 and rng:zeroOrMore"><oneOrMore xmlns="http://relaxng.org/ns/structure/1.0"><xsl:copy-of select="rng:zeroOrMore/*"/></oneOrMore></xsl:when><xsl:when test="self::rng:zeroOrMore/rng:ref/@name eq 'model.global' and preceding-sibling::rng:*[1][self::rng:zeroOrMore/rng:ref/@name eq 'model.global']"/><xsl:when test="$entCount>0 or $stripped='true'"><xsl:element namespace="http://relaxng.org/ns/structure/1.0" name="{$element}"><xsl:copy-of select="@*|*|text()|processing-instruction()"/></xsl:element></xsl:when></xsl:choose></xsl:for-each></xsl:template>
<xsl:template name="odd2odd-simplifyODD"><xsl:variable name="element"><xsl:value-of select="local-name(.)"/></xsl:variable><xsl:variable name="minOmaxO" select="tei:minOmaxO( @minOccurs, @maxOccurs )"/><xsl:variable name="min" select="$minOmaxO[1]"/><xsl:variable name="max" select="$minOmaxO[2]"/><xsl:variable name="otherAtts" select="@* except ( @minOccurs, @maxOccurs )"/><!--
for each Pure ODD content model,
remove reference to any elements which have been
deleted, or to classes which are empty.
This may make the container empty,
so that is only put back in if there is some content
--><xsl:variable name="contents"><WHAT><xsl:for-each select="a:*|tei:*|rng:*|processing-instruction()"><xsl:choose><xsl:when test="self::a:* | self::processing-instruction() "><xsl:copy/></xsl:when><!-- Keep for now to support anyXML --><xsl:when test="self::rng:element | self::rng:name | self::rng:attribute"><xsl:copy><xsl:copy-of select="@*"/><xsl:apply-templates mode="odd2odd-copy"/></xsl:copy></xsl:when><!-- end anyXML section --><xsl:when test="self::tei:dataRef[@name] | self::tei:textNode | self::tei:valList | self::tei:anyElement"><xsl:copy-of select="."/></xsl:when><xsl:when test="self::tei:classRef or self::tei:elementRef or self::tei:macroRef or self::tei:dataRef"><xsl:variable name="N" select="@key"/><xsl:variable name="current" select="."/><xsl:for-each select="$ODD"><xsl:choose><xsl:when test="$stripped='true'"><xsl:copy-of select="$current"/></xsl:when><xsl:when test="key('odd2odd-DELETE',$N)"/><xsl:otherwise><xsl:copy-of select="$current"/></xsl:otherwise></xsl:choose></xsl:for-each></xsl:when><xsl:otherwise><xsl:call-template name="odd2odd-simplifyODD"/></xsl:otherwise></xsl:choose></xsl:for-each></WHAT></xsl:variable><xsl:variable name="entCount" select="count($contents/WHAT/*)"/><xsl:for-each select="$contents/WHAT"><xsl:choose><xsl:when test="$entCount eq 1 and local-name(*) eq $element"><xsl:copy-of select="@*|*|text()|processing-instruction()"/></xsl:when><!-- sequence or alternate that's zero or one containing sequence or alternate that's zero or one--><xsl:when test="$element=('sequence','alternate') and $min eq 0 and $max eq 1 and $entCount eq 1 and (tei:sequence|tei:alternate)[ tei:minOmaxO( @minOccurs, @maxOccurs )[1] eq 0 and tei:minOmaxO( @minOccurs, @maxOccurs )[2] eq -1 ]"><xsl:copy-of select="@*|*|text()|processing-instruction()"/></xsl:when><xsl:when test="$element=('sequence','alternate') and $min eq 0 and $max eq 1 and $entCount eq 1 and (tei:sequence|tei:alternate)[ tei:minOmaxO( @minOccurs, @maxOccurs )[1] eq 1 and tei:minOmaxO( @minOccurs, @maxOccurs )[2] eq -1 ]"><xsl:copy-of select="@*|*|text()|processing-instruction()"/></xsl:when><!-- sequence or alternate that's zero or more containing sequence or alternate that's zero or more --><xsl:when test="$element=('sequence','alternate') and $min eq 1 and $max eq -1 and $entCount eq 1 and (tei:sequence|tei:alternate)[ tei:minOmaxO( @minOccurs, @maxOccurs )[1] eq 0 and tei:minOmaxO( @minOccurs, @maxOccurs )[2] eq -1 ]"><xsl:copy><xsl:copy-of select="@*"/><xsl:copy-of select="(tei:sequence|tei:alternate)/*"/></xsl:copy></xsl:when><!-- classRef that's 0 or more immediately following a classRef that's 0 or more --><xsl:when test="self::tei:classRef[ @key eq 'model.global' and tei:minOmaxO( @minOccurs, @maxOccurs )[1] eq 0 and tei:minOmaxO( @minOccurs, @maxOccurs )[2] eq -1 ] and preceding-sibling::tei:*[1][ self::tei:classRef/@key eq 'model.global' and tei:minOmaxO( @minOccurs, @maxOccurs )[1] eq 0 and tei:minOmaxO( @minOccurs, @maxOccurs )[2] eq -1 ]"/><xsl:when test="$entCount gt 0 or $stripped='true'"><xsl:element namespace="http://www.tei-c.org/ns/1.0" name="{$element}"><xsl:attribute name="minOccurs" select="$min"/><xsl:attribute name="maxOccurs" select="if ($max eq -1) then 'unbounded' else $max"/><!-- Copy the attributes declared on the source element --><xsl:copy-of select="$otherAtts"/><!--joeytakeda iss241: I'm not sure if the @* below is necessary --><!-- given that it would be copying the attributes on the temporary --><!-- WHAT element, which won't have attributes AFAICT --><xsl:copy-of select="@*|*|text()|processing-instruction()"/></xsl:element></xsl:when></xsl:choose></xsl:for-each></xsl:template>
following template, added 2016-06-06 by Syd Bauman, completely
supresses <exemplum> elements from the TEI source iff
$suppressTEIexamples (a parameter) is set to "true". Note that
<exemplum> elements from the ODD customization file are still
copied through.
<xsl:template name="odd2odd-processAttributes"><xsl:param name="ORIGINAL"/><xsl:param name="objectName"/><!-- we are sitting in the ODD --><!-- first put in the ones we know take precedence as replacements --><xsl:for-each select="tei:attList/tei:attDef[@mode eq 'replace' and @ident=$ORIGINAL/tei:attList//tei:attDef/@ident]"><attDef xmlns="http://www.tei-c.org/ns/1.0"><xsl:apply-templates select="@*"/><xsl:apply-templates mode="justcopy"/></attDef></xsl:for-each><xsl:for-each select="tei:attList/tei:attDef[@mode eq 'add' or not(@mode)]"><attDef xmlns="http://www.tei-c.org/ns/1.0"><xsl:apply-templates select="@*[not(name()='mode')]"/><xsl:apply-templates mode="justcopy"/></attDef></xsl:for-each><!-- class attributes are ones where there is no direct correspondence in
the source for this element --><xsl:if test="$ORIGINAL/self::tei:elementSpec"><xsl:apply-templates mode="justcopy" select="tei:attList/tei:attDef [ ( @mode eq 'change' or @mode eq 'delete' or @mode eq 'replace' ) and not( @ident = $ORIGINAL/tei:attList//tei:attDef/@ident ) ]"/></xsl:if><!-- any direct attRef elements --><xsl:apply-templates mode="justcopy" select="tei:attList/tei:attRef"/><!-- now look at each of the original object's attributes and see
if we have an update --><xsl:for-each select="$ORIGINAL/tei:attList"><!-- original source context --><!-- first looking at nested attList --><xsl:for-each select="tei:attList"><attList xmlns="http://www.tei-c.org/ns/1.0"><xsl:copy-of select="@org"/><xsl:for-each select="tei:attDef"><xsl:variable name="ATT" select="."/><xsl:variable name="lookingAt"><xsl:value-of select="concat(../../../@ident,'_',@ident)"/></xsl:variable><xsl:choose><xsl:when test="ancestor::tei:classSpec and $ODD/key('odd2odd-DELETEATT',$lookingAt)"/><xsl:when test="$ODD/key('odd2odd-DELETEATT',$lookingAt)"><xsl:copy-of select="$ODD/key('odd2odd-DELETEATT',$lookingAt)"/></xsl:when><xsl:when test="$ODD/key('odd2odd-REPLACEATT',$lookingAt)"/><xsl:when test="$ODD/key('odd2odd-CHANGEATT',$lookingAt)"><xsl:call-template name="odd2odd-mergeAttribute"><xsl:with-param name="New" select="$ODD/key('odd2odd-CHANGEATT',$lookingAt)"/><xsl:with-param name="Old" select="$ATT"/></xsl:call-template></xsl:when><xsl:otherwise><xsl:copy-of select="$ATT"/></xsl:otherwise></xsl:choose></xsl:for-each></attList></xsl:for-each><!-- now the normal attributes --><xsl:variable name="atts"><xsl:for-each select="tei:attDef"><xsl:variable name="ATT" select="."/><xsl:variable name="lookingAt"><xsl:value-of select="concat(../../@ident,'_',@ident)"/></xsl:variable><xsl:choose><xsl:when test="ancestor::tei:classSpec and $ODD/key('odd2odd-DELETEATT',$lookingAt)"/><xsl:when test="$ODD/key('odd2odd-DELETEATT',$lookingAt)"><xsl:copy-of select="$ODD/key('odd2odd-DELETEATT',$lookingAt)"/></xsl:when><xsl:when test="$ODD/key('odd2odd-REPLACEATT',$lookingAt)"/><xsl:when test="$ODD/key('odd2odd-CHANGEATT',$lookingAt)"><xsl:call-template name="odd2odd-mergeAttribute"><xsl:with-param name="New" select="$ODD/key('odd2odd-CHANGEATT',$lookingAt)"/><xsl:with-param name="Old" select="$ATT"/></xsl:call-template></xsl:when><xsl:otherwise><xsl:copy-of select="$ATT"/></xsl:otherwise></xsl:choose></xsl:for-each></xsl:variable><xsl:choose><xsl:when test="@org"><attList xmlns="http://www.tei-c.org/ns/1.0"><xsl:copy-of select="@org"/><xsl:copy-of select="$atts"/></attList></xsl:when><xsl:otherwise><xsl:copy-of select="$atts"/></xsl:otherwise></xsl:choose></xsl:for-each></xsl:template>
<xsl:template name="odd2odd-getversion"><!--
Note:
This template generates a single string which is the concatonation
of all the fileDesc/editionStmt/edition elements. Luckily it only
reads p5subset.xml which has one and only one such element. See
https://github.com/TEIC/Stylesheets/issues/355.
--><xsl:choose><xsl:when test="key('odd2odd-SCHEMASPECS',$whichSchemaSpec)"><xsl:for-each select="key('odd2odd-SCHEMASPECS',$whichSchemaSpec)"><xsl:variable name="source" select="tei:workOutSource(.)"/><xsl:for-each select="document($source)/*/tei:teiHeader/tei:fileDesc/tei:editionStmt/tei:edition"><xsl:value-of select="."/></xsl:for-each></xsl:for-each></xsl:when><xsl:otherwise><xsl:for-each select="document($DEFAULTSOURCE)/*/tei:teiHeader/tei:fileDesc/tei:editionStmt/tei:edition"><xsl:value-of select="."/></xsl:for-each></xsl:otherwise></xsl:choose></xsl:template>
<xsl:template name="odd2odd-processConstraints"><xsl:param name="ORIGINAL"/><xsl:param name="elementName"/><!-- first put in the ones we know take precedence --><xsl:apply-templates mode="justcopy" select="tei:constraintSpec[@mode eq 'add' or not(@mode)]"/><xsl:apply-templates mode="justcopy" select="tei:constraintSpec[@mode eq 'replace']"/><xsl:apply-templates mode="justcopy" select="tei:constraintSpec[@mode eq 'change']"/><xsl:for-each select="$ORIGINAL"><!-- original source context --><xsl:for-each select="descendant::tei:constraintSpec"><!-- 2022-01-28: added descendant axis to process all descendant <constraintSpec> elements
(e.g. elementSpec/attList/constraintSpec) --><xsl:variable name="CONSTRAINT" select="."/><xsl:variable name="lookingAt"><xsl:value-of select="@ident"/></xsl:variable><xsl:for-each select="$ODD"><xsl:choose><xsl:when test="key('odd2odd-DELETECONSTRAINT',$lookingAt)"/><xsl:when test="key('odd2odd-REPLACECONSTRAINT',$lookingAt)"/><xsl:when test="key('odd2odd-CHANGECONSTRAINT',$lookingAt)"/><xsl:otherwise><xsl:copy-of select="$CONSTRAINT"/></xsl:otherwise></xsl:choose></xsl:for-each></xsl:for-each></xsl:for-each></xsl:template>
<xsl:template match="tei:ptr | tei:listRef/tei:ref" mode="pass3"><xsl:choose><xsl:when test="starts-with(@target,'#') and (ancestor::tei:remarks or parent::tei:listRef or ancestor::tei:valDesc) and not(id(substring(@target,2)))"><xsl:variable name="target" select="substring(@target,2)"/><xsl:variable name="sourceDoc" select="tei:workOutSource(.)"/><!-- the chapter ID is on the highest ancestor or self div --><xsl:variable name="chapter" select="document($sourceDoc)/id($target)/ancestor-or-self::tei:div[not(ancestor::tei:div)]/@xml:id"/><xsl:choose><xsl:when test="(string-length(normalize-space(.)) > 0) or processing-instruction() or comment()"><ref xmlns="http://www.tei-c.org/ns/1.0" target="https://www.tei-c.org/release/doc/tei-p5-doc/en/html/{$chapter}.html#{$target}"><xsl:apply-templates mode="#current"/></ref></xsl:when><xsl:when test="document($sourceDoc)/id($target)"><ref xmlns="http://www.tei-c.org/ns/1.0" target="https://www.tei-c.org/release/doc/tei-p5-doc/en/html/{$chapter}.html#{$target}"><xsl:for-each select="document($sourceDoc)/id($target)"><xsl:number count="tei:div" format="1.1.1." level="multiple"/><xsl:text></xsl:text><xsl:value-of select="tei:head"/></xsl:for-each></ref></xsl:when><xsl:otherwise><xsl:copy><xsl:apply-templates select="@*|*|text()|processing-instruction()" mode="pass3"/></xsl:copy></xsl:otherwise></xsl:choose></xsl:when><xsl:otherwise><xsl:copy><xsl:apply-templates select="@*|*|text()|processing-instruction()" mode="pass3"/></xsl:copy></xsl:otherwise></xsl:choose></xsl:template>
<xsl:template name="odd2odd-amINeeded"><!--
How can a class be ok?
a) if an element is a member of it and
b) its referred to in a content model
c) some other class is a member of it, and that class is OK
d) its a member of some other class, and that class is OK
--><xsl:variable name="k" select="@ident"/><xsl:choose><xsl:when test="$autoGlobal='true' and starts-with(@ident,'att.global')">y</xsl:when><xsl:when test="@type eq 'model' and key('odd2odd-REFED',$k)">y</xsl:when><xsl:when test="@type eq 'atts' and key('odd2odd-ATTREFED',$k)">y</xsl:when><xsl:when test="@type eq 'atts' and key('odd2odd-ELEMENT_MEMBERED',$k)">y</xsl:when><xsl:when test="@type eq 'atts' and key('odd2odd-CLASS_MEMBERED',$k)"><xsl:for-each select="key('odd2odd-CLASS_MEMBERED',$k)"><xsl:call-template name="odd2odd-amINeeded"/></xsl:for-each></xsl:when><xsl:when test="@type eq 'model' and tei:classes/tei:memberOf"><xsl:for-each select="tei:classes/tei:memberOf/key('odd2odd-IDENTS',@key)"><xsl:call-template name="odd2odd-amINeeded"/></xsl:for-each></xsl:when></xsl:choose></xsl:template>
following param, added 2016-06-06 by Syd Bauman for use by TEI
in Libraries Best Practices Guidelines. If set to 'true' then
all <exmplum> elements from TEI source or summarily dropped,
whereas <exemplum> elements in ODD customization file are
copied through.
<xsl:variable name="ODD"><xsl:for-each select="/*"><xsl:copy><xsl:attribute name="xml:base" select="document-uri(/)"/><xsl:copy-of select="@*"/><xsl:if test="$useVersionFromTEI='true'"><xsl:processing-instruction name="TEIVERSION"><!--
Generate a string based on the fileDesc/editionStmt/edition
element(s) in the p5subset.xml file. (Note that this would
look ugly if there were more than one editionStmt/edition,
but there is only one in that file.)
See ticket https://github.com/TEIC/Stylesheets/issues/355.
--><xsl:call-template name="odd2odd-getversion"/></xsl:processing-instruction></xsl:if><xsl:apply-templates mode="pass0"/></xsl:copy></xsl:for-each></xsl:variable>
<xsl:function name="tei:minOmaxO" as="xs:integer+"><!-- Input: the string values of the attributes @minOccurs and --><!-- @maxOccurs --><!-- Oputput: a sequence of 2 integers representing the integer --><!-- values thereof with -1 used to indicate "unbounded" --><xsl:param name="minOccurs"/><xsl:param name="maxOccurs"/><!-- get the value of @minOccurs, defaulting to "1" --><xsl:variable name="minOccurs" select="( $minOccurs, '1')[1]"/><!-- get the value of @maxOccurs, defaulting to "1" --><xsl:variable name="maxOccurs" select="( $maxOccurs, '1')[1]"/><!-- We now have two _string_ representations of the attrs, but --><!-- we need integers. So cast them, converting "unbounded" to --><!-- a special flag value (-1): --><xsl:variable name="min" select="xs:integer( $minOccurs )"/><xsl:variable name="max"><xsl:choose><xsl:when test="$maxOccurs castable as xs:integer"><xsl:value-of select="xs:integer( $maxOccurs )"/></xsl:when><xsl:otherwise><!-- Must be "unbounded". --><xsl:value-of select="-1"/></xsl:otherwise></xsl:choose></xsl:variable><xsl:sequence select="( $min, $max )"/></xsl:function>