Change2change.xslt
Jump to navigation
Jump to search
The P5 <change> element is significantly different than the P4 <change> element. This stylesheet reads in a TEI P4 XML file and writes out the same file but with P5-format <change> elements.
<?xml version="1.0" encoding="utf-8"?>
<!-- Tiny XSLT 1.0 stylesheet that reads in a TEI file with <change> elements -->
<!-- that conform to P4, and writes out the same with <change> elements that -->
<!-- are likely to conform to P5 (pre-release 0.3.1). -->
<!-- Copyleft 2006 Syd Bauman and the Text Encoding Initiative Consortium -->
<!-- The output of this stylesheet is not P5-compliant XML; in fact, even the -->
<!-- one element we are changing, namely <change>, may not be valid P5. This is -->
<!-- because although we move all the bits of information to the right place, it -->
<!-- may still be in the wrong format. E.g., a <date value="2006-01-31">31 Jan -->
<!-- 06</date> will be transformed to the valid when="2006-01-31", but a <date>31 -->
<!-- Jan 06</date> will be tranformed to the invalid when="31 Jan 06". -->
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:tei="http://www.tei-c.org/ns/1.0"
version="1.0">
<xsl:import href="Copy-All.xsl"/>
<xsl:output method="xml"
encoding="UTF-8"
cdata-section-elements="eg"/>
<!-- special template for <change> elements that have to change -->
<xsl:template match="revisionDesc/change">
<xsl:element name="change">
<xsl:attribute name="when">
<!-- For the value of the new when= attribute ... -->
<!-- look at my child <date> element, -->
<xsl:choose>
<!-- if it has a value= attribute, use its value -->
<xsl:when test="./date/@value">
<xsl:value-of select="./date/@value"/>
</xsl:when>
<!-- if not, use its content -->
<xsl:otherwise>
<xsl:value-of select="./date/text()"/>
</xsl:otherwise>
</xsl:choose>
</xsl:attribute>
<xsl:attribute name="who">
<!-- For the value of the new who= attribute ... -->
<!-- look at my child <respStmt>'s first <name> child ... -->
<!-- (warn if there's more than 1 <name> child of <respStmt>) -->
<xsl:if test="count(./respStmt/name)>1">
<xsl:message> warning: more than one <name> child of <respStmt>, using the first </xsl:message>
</xsl:if>
<xsl:variable name="respName">
<xsl:choose>
<!-- ... if it has a key=, use its value -->
<xsl:when test="./respStmt/name/@key">
<xsl:value-of select="./respStmt/name/@key"/>
</xsl:when>
<!-- ... if no key=, if it has a reg=, use its value -->
<xsl:when test="./respStmt/name/@reg">
<xsl:value-of select="./respStmt/name/@reg"/>
</xsl:when>
<!-- ... neither key= nor reg=, use content -->
<xsl:otherwise>
<xsl:value-of select="./respStmt/name/text()"/>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<!-- ... now that we have a name, strip out icky characters -->
<xsl:variable name="respVal" select='translate(normalize-space($respName),"-,'&#$%^!~`={}[]<>?/:; +=\|@","-")'/>
<!-- [Note that hyphens are left in place, as they are valid NAME characters.] -->
<!-- This is not the right way to do this. What we really want is not to strip -->
<!-- out the few non-NAME characters I can think of and type easily, but rather -->
<!-- we'd prefer to keep only the NAME characters and ditch everything else. -->
<!-- I don't know if that can be done in XSLT 1.0, and if it can, I don't know -->
<!-- how to do it. Note also that we do not check that the first char is -->
<!-- a NAMESTART character. -->
<!-- ... and stick a "#" in front -->
<xsl:text>#</xsl:text>
<xsl:value-of select="$respVal"/>
</xsl:attribute>
<!-- content of new <change> is the content of old <change>'s child <item> -->
<xsl:apply-templates select="./item/*|./item/text()|./item/processing-instruction()|./item/comment()"/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
Syd 06:51, 26 May 2006 (BST)