<xsl:stylesheet xmlns:xd="http://www.pnp-software.com/XSLTdoc" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:tei="http://www.tei-c.org/ns/1.0" xmlns="http://www.tei-c.org/ns/1.0" version="1.0" exclude-result-prefixes="xd tei">
  
  <xd:doc type="stylesheet">
    
<xd:short>Stylesheet for TEI P5 MULTEXT-East morphosyntactic specifications. 
    
</xd:short>
    
<xd:author>Tomaž Erjavec, <A href="http://nl.ijs.si/et/">http://nl.ijs.si/et/</A></xd:author>
    
<xd:date>2010-04-23</xd:date>
    
<xd:detail>
      From MULTEXT-East V4 morphosyntactic specifications, encoded as tables in TEI P5 (teiLite),
      generates two TEI P5 libraries. The feature library gives the definitions of the 
      categories (parts-of-speech), their attributes and their values.
      The feature-structure library gives the list of MSDs with pointers to their attribute-value definitions.
      Supports localisation, i.e. can output the libraries in different languages.
    
</xd:detail>
    
<xd:copyright> This library is free software; you can redistribute it and/or modify it under
    the terms of the GNU Lesser General Public License as published by the Free Software
    Foundation; either version 2.1 of the License, or (at your option) any later version.
    This library is distributed in the hope that it will be useful, but WITHOUT ANY
    WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
    PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You
    should have received a copy of the GNU Lesser General Public License along with this
    library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite
    330, Boston, MA 02111-1307 USA 
</xd:copyright>
  
</xd:doc>

  
  <xd:doc type="string">For multilingual specifications selects which language to process.</xd:doc>

  
<xsl:param name="lang" />

  
  <xd:doc type="string">
    Optional list of MSDs, separated by spaces. 
    If given, a TEI P5 feature-structure library will also be generated
    giving the the MSDs as feature-structure IDs, 
    and their decomposition into feature-value pairs, defined in the feature library.
    If empty, we try to take it from the specifications.
  
</xd:doc>

  
<xsl:param name="msds" />
  
  <xd:doc type="string">Input localisation for the MSDs.</xd:doc>

  
<xsl:param name="lang-in">en</xsl:param>
  
  <xd:doc type="string">Output localisations for the features.</xd:doc>

  
<xsl:param name="lang-out">en</xsl:param>

  
<!--xd:doc type="string">Name of FS type, i.e. category.</xd:doc>
  <xsl:variable name="catatt">
    <xsl:text>PoS</xsl:text>
  </xsl:variable
-->

  
<xsl:output method="xml" indent="yes" omit-xml-declaration="yes" />

  
<xsl:key name="id" match="tei:*" use="@xml:id" />
  
  
  <xd:doc>
    Output specifications as feature library, per PoS, and then, if given, MSDs as a fs library.
  
</xd:doc>

  
<xsl:template match="/">
    
<!--xsl:processing-instruction name="oxygen">
      <xsl:text>RNGSchema="schema/tei_mte.rnc" type="compact"</xsl:text>
    </xsl:processing-instruction
-->
    
<xsl:comment>Automatically generated from XML source - edit at you own risk!</xsl:comment>
    
<!--fsdDecl-->
    
<div>
      
<xsl:copy-of select="/tei:div/@*" />
      
<xsl:variable name="lang" select="@select" />
      
<xsl:choose>
        
<xsl:when test="normalize-space($lang)">
          
<xsl:attribute name="select">
            
<xsl:value-of select="$lang" />
          
</xsl:attribute>
        
</xsl:when>
      
</xsl:choose>
      
<xsl:text>
</xsl:text>
      
<head>
        
<xsl:text>MULTEXT-East morphosyntactic specifications as a TEI FS library</xsl:text>
      
</head>
      
<xsl:text>
</xsl:text>
      
<xsl:copy-of select="tei:div/tei:head | tei:div/tei:docAuthor | tei:div/tei:docDate | tei:div/tei:list[@type='gloss']" />
      
<xsl:text>
</xsl:text>
      
<fLib>
        
<xsl:text>
</xsl:text>
        
<xsl:for-each select="//tei:table[@n='msd.cat']">
          
<xsl:call-template name="fLib-PoS" />
        
</xsl:for-each>
      
</fLib>
      
<xsl:choose>
        
<xsl:when test="$msds">
          
<xsl:text>
</xsl:text>
          
<fvLib>
            
<xsl:text>
</xsl:text>
            
<xsl:call-template name="fs-msds">
              
<xsl:with-param name="msds" select="$msds" />
            
</xsl:call-template>
          
</fvLib>
          
<xsl:text>
</xsl:text>
        
</xsl:when>
        
<xsl:when test="//tei:cell[@role='msd']">
          
<xsl:text>
</xsl:text>
          
<fvLib>
            
<xsl:text>
</xsl:text>
            
<xsl:for-each select="//tei:cell[@role='msd']">
              
<xsl:call-template name="fs-msd">
                
<xsl:with-param name="msd" select="." />
              
</xsl:call-template>
            
</xsl:for-each>
          
</fvLib>
          
<xsl:text>
</xsl:text>
        
</xsl:when>
      
</xsl:choose>
      
<xsl:text>
</xsl:text>
    
</div>
    
<!--/fsdDecl-->
  
</xsl:template>
  
  
  <xd:doc>
    Output one PoS as features. 
    Each feature gives the attribute name, value name, and position+code based ID.
  
</xd:doc>

  
<xsl:template name="fLib-PoS">
    
<xsl:variable name="catname">
      
<xsl:call-template name="cell">
        
<xsl:with-param name="row">type</xsl:with-param>
        
<xsl:with-param name="col">value</xsl:with-param>
        
<xsl:with-param name="lan" select="$lang-out" />
      
</xsl:call-template>
    
</xsl:variable>
    
<xsl:variable name="catcode">
      
<xsl:call-template name="cell">
        
<xsl:with-param name="row">type</xsl:with-param>
        
<xsl:with-param name="col">code</xsl:with-param>
        
<xsl:with-param name="lan" select="$lang-in" />
      
</xsl:call-template>
    
</xsl:variable>
    
<xsl:variable name="catatt">
      
<xsl:call-template name="cell">
        
<xsl:with-param name="row">type</xsl:with-param>
        
<xsl:with-param name="col">name</xsl:with-param>
        
<xsl:with-param name="lan" select="$lang-out" />
      
</xsl:call-template>
    
</xsl:variable>
    
<xsl:comment>
      
<xsl:number value="position()" format="1" />
      
<xsl:value-of select="concat('. ',$catname,' (',$catcode,')')" />
    
</xsl:comment>
    
<xsl:text>
</xsl:text>
    
<xsl:call-template name="feature">
      
<xsl:with-param name="catcode" select="$catcode" />
      
<xsl:with-param name="position" select="0" />
      
<xsl:with-param name="attribute" select="$catatt" />
      
<xsl:with-param name="value" select="$catname" />
      
<xsl:with-param name="select" select="lang" />
    
</xsl:call-template>
    
<xsl:text>
</xsl:text>
    
<xsl:for-each select="tei:row[@role='attribute']">
      
<xsl:variable name="attribute">
        
<xsl:call-template name="cell">
          
<xsl:with-param name="col">name</xsl:with-param>
        
<xsl:with-param name="lan" select="$lang-out" />
        
</xsl:call-template>
      
</xsl:variable>
      
<xsl:variable name="position">
        
<xsl:call-template name="cell">
          
<xsl:with-param name="col">position</xsl:with-param>
        
</xsl:call-template>
      
</xsl:variable>
      
<xsl:for-each select="tei:cell/tei:table/tei:row[@role='value']">
        
<xsl:call-template name="feature">
          
<xsl:with-param name="catcode" select="$catcode" />
          
<xsl:with-param name="position" select="$position" />
          
<xsl:with-param name="code">
            
<xsl:call-template name="cell">
              
<xsl:with-param name="col">code</xsl:with-param>
              
<xsl:with-param name="lan" select="$lang-in" />
            
</xsl:call-template>
          
</xsl:with-param>
          
<xsl:with-param name="attribute" select="$attribute" />
          
<xsl:with-param name="value">
            
<xsl:call-template name="cell">
              
<xsl:with-param name="col">name</xsl:with-param>
              
<xsl:with-param name="lan" select="$lang-out" />
            
</xsl:call-template>
          
</xsl:with-param>
        
</xsl:call-template>
      
</xsl:for-each>
      
<xsl:text>
</xsl:text>
    
</xsl:for-each>
  
</xsl:template>
     
  
  <xd:doc>
    Outputs one feature, but only if value is set.
    
<xd:param name="catcode" type="string">Code of the PoS</xd:param>
    
<xd:param name="position" type="number">Position number</xd:param>
    
<xd:param name="code" type="number">Code of the value</xd:param>
    
<xd:param name="attribute" type="number">Name of the attribute</xd:param>
    
<xd:param name="value" type="number">Name of the value</xd:param>
  
</xd:doc>

  
<xsl:template name="feature">
    
<xsl:param name="catcode" />
    
<xsl:param name="position" />
    
<xsl:param name="code" />
    
<xsl:param name="attribute" />
    
<xsl:param name="value" />
    
<xsl:param name="select" />
    
<xsl:if test="normalize-space($value)">
      
<f name="{$attribute}">
        
<xsl:attribute name="xml:id">
          
<xsl:value-of select="concat($catcode,$position,'.',$code)" />
        
</xsl:attribute>
        
<xsl:attribute name="xml:lang">
          
<xsl:value-of select="$lang-out" />
        
</xsl:attribute>
        
<xsl:if test="$select">
          
<xsl:attribute name="select">
            
<xsl:value-of select="$select" />
          
</xsl:attribute>
        
</xsl:if>
        
<symbol value="{$value}" />
      
</f>
      
<xsl:text>
</xsl:text>
    
</xsl:if>
  
</xsl:template>

  
  <xd:doc>
    Output one cell in correct localisation. Assumes table or row context node.
    
<xd:param name="row" type="string">The @role of the row; if empty, row is assumed as context node.</xd:param>
    
<xd:param name="col" type="string">The @role of the cell.</xd:param>
    
<xd:param name="lan" type="string">The @xml:lang of the cell.</xd:param>
  
</xd:doc>

  
<xsl:template name="cell">
    
<xsl:param name="row" />
    
<xsl:param name="col" />
    
<xsl:param name="lan" />
    
<xsl:choose>
      
<xsl:when test="$row">
        
<xsl:choose>
          
<xsl:when test="$lan and $lang">
            
<xsl:value-of select="tei:row[@role=$row][tei:cell[@role='lang']=$lang or not(tei:cell[@role='lang'])] /tei:cell[@role=$col][ancestor-or-self::tei:*[@xml:lang][1][@xml:lang=$lan]]" />
          
</xsl:when>
          
<xsl:when test="$lan">
            
<xsl:value-of select="tei:row[@role=$row] /tei:cell[@role=$col][ancestor-or-self::tei:*[@xml:lang][1][@xml:lang=$lan]]" />
          
</xsl:when>
          
<xsl:otherwise>
            
<xsl:value-of select="tei:row[@role=$row][tei:cell[@role='lang']=$lang or not(tei:cell[@role='lang'])] /tei:cell[@role=$col]" />
          
</xsl:otherwise>
        
</xsl:choose>
      
</xsl:when>
      
<xsl:otherwise>
        
<xsl:choose>
          
<xsl:when test="$lan and $lang">
            
<xsl:value-of select="tei:cell[@role=$col][../tei:cell[@role='lang']=$lang or not(../tei:cell[@role='lang'])] [ancestor-or-self::tei:*[@xml:lang][1][@xml:lang=$lan]]" />
          
</xsl:when>
          
<xsl:when test="$lan">
            
<xsl:value-of select="tei:cell[@role=$col] [ancestor-or-self::tei:*[@xml:lang][1][@xml:lang=$lan]]" />
          
</xsl:when>
          
<xsl:otherwise>
            
<xsl:value-of select="tei:cell[@role=$col][../tei:cell[@role='lang']=$lang or not(../tei:cell[@role='lang'])]" />
          
</xsl:otherwise>
        
</xsl:choose>
      
</xsl:otherwise>
    
</xsl:choose>
  
</xsl:template>

  
  <xd:doc>
    MSD 2 fsLib processing with localisation.
    This template splits the list of MSDs and passes them to fs-msds.
    
<xd:param name="msds" type="string">Space separated list of MSDs.</xd:param>
  
</xd:doc>

  
<xsl:template name="fs-msds">
    
<xsl:param name="msds" />
    
<xsl:choose>
      
<xsl:when test="contains($msds,' ')">
        
<xsl:variable name="msd" select="substring-before($msds,' ')" />
        
<xsl:variable name="rest" select="substring-after($msds,' ')" />
        
<xsl:call-template name="fs-msd">
          
<xsl:with-param name="msd" select="$msd" />
        
</xsl:call-template>
        
<xsl:call-template name="fs-msds">
          
<xsl:with-param name="msds" select="$rest" />
        
</xsl:call-template>
      
</xsl:when>
      
<xsl:otherwise>
        
<xsl:call-template name="fs-msd">
          
<xsl:with-param name="msd" select="$msds" />
        
</xsl:call-template>
      
</xsl:otherwise>
    
</xsl:choose>
  
</xsl:template>

  
  <xd:doc>Process one MSD, output a feature-structure</xd:doc>

  
<xsl:template name="fs-msd">
    
<xsl:param name="msd" />
    
<fs>
      
<xsl:attribute name="xml:id">
        
<xsl:value-of select="$msd" />
      
</xsl:attribute>
      
<xsl:attribute name="xml:lang">
        
<xsl:value-of select="$lang-out" />
      
</xsl:attribute>
      
<xsl:if test="$lang">
        
<xsl:attribute name="select">
          
<xsl:value-of select="$lang" />
        
</xsl:attribute>
      
</xsl:if>
      
<xsl:attribute name="feats">
        
<xsl:call-template name="msdfs-feature">
          
<xsl:with-param name="pos" select="substring($msd,1,1)" />
          
<xsl:with-param name="str" select="$msd" />
          
<xsl:with-param name="n">0</xsl:with-param>
        
</xsl:call-template>
      
</xsl:attribute>
    
</fs>
    
<xsl:text>
</xsl:text>
  
</xsl:template>

  
  <xd:doc>
    Output one feature reference.
    Currently, hyphen (-) is not output; arguably wrong.
    No checking is made on the legality of the features. 
    This can be done with validation of the XML document including the fLib and fsLib and with msd-expand.xsl.
  
</xd:doc>

  
<xsl:template name="msdfs-feature">
    
<xsl:param name="pos" />
    
<xsl:param name="str" />
    
<xsl:param name="n" />
    
<xsl:if test="normalize-space($str)">
      
<xsl:variable name="name" select="substring($str,1,1)" />
      
<xsl:if test="$name != '-'">
        
<xsl:if test="$n &gt; 0">
          
<xsl:text> </xsl:text>
        
</xsl:if>
        
<xsl:text>#</xsl:text>
        
<xsl:value-of select="$pos" />
        
<xsl:value-of select="$n" />
        
<xsl:text>.</xsl:text>
        
<xsl:if test="$n &gt; 0">
          
<xsl:value-of select="$name" />
        
</xsl:if>
      
</xsl:if>
      
<xsl:call-template name="msdfs-feature">
        
<xsl:with-param name="pos" select="$pos" />
        
<xsl:with-param name="str" select="substring($str,2)" />
        
<xsl:with-param name="n" select="$n+1" />
      
</xsl:call-template>
    
</xsl:if>
  
</xsl:template>
 
</xsl:stylesheet>






































v