<xsl:stylesheet xmlns:its="http://www.w3.org/2005/11/its"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:XSL="http://www.w3.org/1999/XSL/TransformAlias"
 exclude-result-prefixes="xsl" version="2.0">

 <xsl:output method="xml" indent="yes" encoding="utf-8"/>
 <xsl:strip-space elements="*"/>
 <xsl:namespace-alias stylesheet-prefix="XSL" result-prefix="xsl"/>
 <xsl:param name="inputDoc">none</xsl:param>
 <xsl:param name="externalRules">none</xsl:param>
 <xsl:variable name="XMLInput" select="doc($inputDoc)" as="node()*"/>

 <xsl:template match="/">
  <XSL:stylesheet version="2.0" xmlns:its="http://www.w3.org/2005/11/its"
   xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
   <XSL:output method="xml" indent="yes" encoding="utf-8"/>
   <XSL:strip-space elements="*"/>
   <XSL:template match="/">
    <XSL:apply-templates mode="Translate" select="@* | node()">
     <XSL:with-param name="existingValue">yes</XSL:with-param>
    </XSL:apply-templates>
   </XSL:template>

   <XSL:template name="output">
    <XSL:param name="value">notset</XSL:param>
    <XSL:param name="type">notset</XSL:param>
    <XSL:choose>
     <XSL:when test="self::element()">
      <XSL:copy>
       <XSL:attribute name="its-transval-elem">
        <XSL:value-of select="$value"/>
       </XSL:attribute>
       <XSL:apply-templates select="@* | node()" mode="Translate">
        <XSL:with-param name="existingValue">
         <XSL:value-of select="$value"/>
        </XSL:with-param>
       </XSL:apply-templates>
      </XSL:copy>
     </XSL:when>
         <XSL:when test="self::attribute()">
            <XSL:copy/>
            <XSL:variable name="attrval">               
               <XSL:text>transval-attr-</XSL:text>     
<XSL:value-of select="concat('p--',substring-before(name(),':'),'--p-')"/>          
               <XSL:value-of select="local-name()"/>
            </XSL:variable>
            <XSL:attribute name="{{$attrval}}">
               <XSL:value-of select="$value"/>
            </XSL:attribute>
         </XSL:when>
    </XSL:choose>
   </XSL:template>

   <xsl:call-template name="localMarkupTemplate"/>
   <xsl:call-template name="recursionTemplate"/>
   <xsl:call-template name="globalRulesTemplate"/>
  </XSL:stylesheet>
 </xsl:template>

 <xsl:template name="gatherRules">
  <xsl:param name="docWithRules"/>
  <xsl:for-each select="$docWithRules//h:rules | $docWithRules//its:rules" xmlns:h="http://www.w3.org/1999/xhtml">
   <xsl:if test="@xlink:href" xmlns:xlink="http://www.w3.org/1999/xlink">
    <xsl:call-template name="gatherRules">
     <xsl:with-param name="docWithRules"
      select="doc(concat(substring-before(base-uri($docWithRules),tokenize(base-uri($docWithRules), '(/)|(\\)')[last()]),@xlink:href))"
     />
    </xsl:call-template>
   </xsl:if>
   <xsl:for-each select=".//h:translateRule | .//its:translateRule | .//translateRule" xmlns:h="http://www.w3.org/1999/xhtml">
    <xsl:copy-of select="."/>
   </xsl:for-each>
  </xsl:for-each>
 </xsl:template>

 <xsl:template name="globalRulesTemplate">
  <xsl:variable name="globalRules">
   <xsl:call-template name="gatherRules">
    <xsl:with-param name="docWithRules">
     <xsl:choose>
      <xsl:when test="$externalRules!='none'">
       <xsl:copy-of select="$XMLInput | doc($externalRules)"/>
      </xsl:when>
      <xsl:otherwise>
       <xsl:copy-of select="$XMLInput"/>
      </xsl:otherwise>
     </xsl:choose>
    </xsl:with-param>
   </xsl:call-template>
  </xsl:variable>
  <xsl:for-each select="$globalRules/*">
   <xsl:variable name="value">
    <xsl:text>'</xsl:text>
    <xsl:value-of select="@translate"/>
    <xsl:text>'</xsl:text>
   </xsl:variable>
   <XSL:template match="{./@selector}" mode="Translate">
    <xsl:variable name="currentRuleEl" select="."/>
    <xsl:for-each select="in-scope-prefixes(.)[not(.='xml')]">
     <xsl:namespace name="{.}"
      select="namespace-uri-for-prefix(.,$currentRuleEl)"/>
    </xsl:for-each>
    <xsl:attribute name="priority">
     <xsl:number/>
    </xsl:attribute>
    <XSL:call-template name="output">
     <XSL:with-param name="value" select="{$value}"/>
     <XSL:with-param name="type">global</XSL:with-param>
    </XSL:call-template>
   </XSL:template>
  </xsl:for-each>
 </xsl:template>

 <xsl:template name="localMarkupTemplate">
  <XSL:template match="*[@its:translate]" priority="+1000" mode="Translate">
   <XSL:call-template name="output">
    <XSL:with-param name="value" select="@its:translate"/>
    <XSL:with-param name="type">local</XSL:with-param>
   </XSL:call-template>
  </XSL:template>
 </xsl:template>

 <xsl:template name="recursionTemplate">
  <XSL:template match="*" priority="-1000" mode="Translate">
   <XSL:param name="existingValue">yes</XSL:param>
   <XSL:choose>
    <XSL:when test="$existingValue='yes'">
     <XSL:call-template name="output">
      <XSL:with-param name="value">yes</XSL:with-param>
      <XSL:with-param name="type">recurse-elem</XSL:with-param>
     </XSL:call-template>
    </XSL:when>
    <XSL:otherwise>
     <XSL:call-template name="output">
      <XSL:with-param name="value">no</XSL:with-param>
      <XSL:with-param name="type">recurse-elem</XSL:with-param>
     </XSL:call-template>
    </XSL:otherwise>
   </XSL:choose>
  </XSL:template>

  <XSL:template match="@*" priority="-1000" mode="Translate">
   <XSL:param name="existingValue">no</XSL:param>
   <XSL:choose>
    <XSL:when test="$existingValue='yes'">
     <XSL:call-template name="output">
      <XSL:with-param name="value">yes</XSL:with-param>
      <XSL:with-param name="type">recurse-attr</XSL:with-param>
     </XSL:call-template>
    </XSL:when>
    <XSL:otherwise>
     <XSL:call-template name="output">
      <XSL:with-param name="value">no</XSL:with-param>
      <XSL:with-param name="type">recurse-attr</XSL:with-param>
     </XSL:call-template>
    </XSL:otherwise>
   </XSL:choose>
  </XSL:template>

 </xsl:template>

</xsl:stylesheet>
