<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:xs="http://www.w3.org/1999/XSL/TransformAlias" xmlns:dsrl="http://purl.oclc.org/dsdl/dsrl"
  xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xi="http://www.w3.org/2001/XInclude"
  exclude-result-prefixes="dsrl xsl xsd xi">
  <!-- Example of how XSLT 2.0 can be used to transform a DSRL map to create
        an XSL styleseet, called DSRLtranform.xsl, that can be used to transform 
        XML instances into validatable documents.

        Also creates a file, DSRLentities.ent that redefines mapped entities in format
        required to allow transformation using DSRLtransform.xsl.

        © ISO SC34/WG1, 2006
  -->
  <xsl:output name="transforms" method="xml" indent="yes"/>
  <xsl:output name="entity-definitions" method="text"/>
  <xsl:output name="mapped-entities" method="text" extension-element-prefixes="#default"/>

  <xsl:namespace-alias stylesheet-prefix="xs" result-prefix="xsl"/>

  <!-- Variable for storing information of local working directory:
        Needs to be customized for local environment -->
  <xsl:param name="output-directory">/DSDL/DSDL8%20Examples/</xsl:param>
  <xsl:param name="entity-redefinition">DSRLentities.ent</xsl:param>
  <xsl:param name="MappedEntities">MappedEntities.ent</xsl:param>

  <xsl:template match="dsrl:maps">
    <xsl:result-document href="{$output-directory}DSRLtransform.xsl" format="transforms">
      <xsl:text disable-output-escaping="yes">
&#60;!DOCTYPE xsl:stylesheet [
&#60;!ENTITY % MappedEntities SYSTEM "</xsl:text>
      <xsl:value-of select="$MappedEntities"/>
      <xsl:text disable-output-escaping="yes">"&#62; %MappedEntities;
]&#62;
</xsl:text>
      <xs:stylesheet version="1.0" xmlns:dsrl="http://purl.oclc.org/dsdl/dsrl">
        <xsl:namespace name="" select="/dsrl:maps/@targetNamespace"/>

        <xs:output method="xml" indent="yes"/>
        <xsl:apply-templates/>
        <xs:template match="*|@*">
          <!--Default rule that allows elements and their attributes to be copied if not otherwise mapped-->
          <xs:copy>
            <xs:apply-templates select="@*"/>
            <xs:apply-templates select="*|text()|comment()|processing-instruction()"/>
          </xs:copy>
        </xs:template>
      </xs:stylesheet>
    </xsl:result-document>
  </xsl:template>

  <!--Process element maps-->
  <xsl:template match="dsrl:element-map">
    <xsl:variable name="target">
      <xsl:choose>
        <xsl:when test="dsrl:name">
          <xsl:if test="dsrl:within"><xsl:value-of select="dsrl:within"/>/</xsl:if>
          <xsl:value-of select="dsrl:name"/>
        </xsl:when>
        <xsl:when test="dsrl:from">
          <xsl:if test="dsrl:within"><xsl:value-of select="dsrl:within"/>/</xsl:if>
          <xsl:value-of select="dsrl:from"/>
        </xsl:when>
      </xsl:choose>
    </xsl:variable>
    <xsl:variable name="source-namespace-name">
      <xsl:choose>
        <xsl:when test="dsrl:name">
          <xsl:for-each select="dsrl:name/namespace::*">
            <xsl:if test="not(name(.)='xml' or name(.)='dsrl')"><xsl:value-of select="name(.)"/>:</xsl:if>
          </xsl:for-each>
        </xsl:when>
        <xsl:when test="dsrl:from">
          <xsl:for-each select="dsrl:from/namespace::*">
            <xsl:if test="not(name(.)='xml' or name(.)='dsrl')"><xsl:value-of select="name(.)"/>:</xsl:if>
          </xsl:for-each>
        </xsl:when>
      </xsl:choose>
    </xsl:variable>
    <xsl:variable name="source-namespace-uri">
      <xsl:choose>
        <xsl:when test="dsrl:name">
          <xsl:for-each select="dsrl:name/namespace::*">
            <xsl:if test="not(name(.)='xml' or name(.)='dsrl')">
              <xsl:value-of select="."/>
            </xsl:if>
          </xsl:for-each>
        </xsl:when>
        <xsl:when test="dsrl:from">
          <xsl:for-each select="dsrl:from/namespace::*">
            <xsl:if test="not(name(.)='xml' or name(.)='dsrl')">
              <xsl:value-of select="."/>
            </xsl:if>
          </xsl:for-each>
        </xsl:when>
      </xsl:choose>
    </xsl:variable>
    <xsl:variable name="new-name">
      <xsl:choose>
        <xsl:when test="dsrl:name">
          <xsl:value-of select="dsrl:name"/>
        </xsl:when>
        <xsl:when test="dsrl:to">
          <xsl:value-of select="dsrl:to"/>
        </xsl:when>
      </xsl:choose>
    </xsl:variable>
    <xsl:variable name="target-namespace-name">
      <xsl:for-each select="dsrl:to/namespace::*">
        <xsl:if test="not(name(.)='xml' or name(.)='dsrl')"><xsl:value-of select="name(.)"/>:</xsl:if>
      </xsl:for-each>
    </xsl:variable>
    <xsl:variable name="target-namespace-uri">
      <xsl:for-each select="dsrl:to/namespace::*">
        <xsl:if test="not(name(.)='xml' or name(.)='dsrl')">
          <xsl:value-of select="."/>
        </xsl:if>
      </xsl:for-each>
    </xsl:variable>
    <xs:template match="{$target}">
      <xsl:if test="not($source-namespace-name='') and not(count(tokenize($source-namespace-name, ':'))>2)">
        <xsl:namespace name="{substring-before($source-namespace-name,':')}">
          <xsl:value-of select="$source-namespace-uri"/>
        </xsl:namespace>
      </xsl:if>
      <xsl:if test="count(tokenize($source-namespace-name, ':'))>2">
        <xsl:message terminate="yes">Error: Only one namespace can be defined for the source of a
        transformation</xsl:message>
      </xsl:if>
      <xsl:if test="dsrl:from and not(substring-before($source-namespace-name,':')=substring-before(dsrl:from,':'))">
        <xsl:message terminate="yes">Error: Namespace declared does not match that used in the element map</xsl:message>
      </xsl:if>
      <xs:element name="{$new-name}">
        <xsl:if test="not($target-namespace-name='') and not(count(tokenize($target-namespace-name, ':'))>2)">
          <xsl:namespace name="{substring-before($target-namespace-name,':')}">
            <xsl:value-of select="$target-namespace-uri"/>
          </xsl:namespace>
        </xsl:if>
        <xsl:if test="count(tokenize($target-namespace-name, ':'))>2">
          <xsl:message terminate="yes">Error: Only one namespace can be defined for the target of a
          transformation</xsl:message>
        </xsl:if>
        <xsl:if test="not(substring-before($target-namespace-name,':')=substring-before(dsrl:to,':'))">
          <xsl:message terminate="yes">Error: Namespace declared does not match that used in the element
          map</xsl:message>
        </xsl:if>
        <xsl:if test="@targetSchemaLocation">
          <xs:attribute name="schemaLocation" namespace="http://www.w3.org/2001/XMLSchema-instance">
            <xsl:value-of select="/dsrl:maps//@targetNamespace"/>
            <xsl:text> </xsl:text>
            <xsl:value-of select="/dsrl:maps//@targetSchemaLocation"/>
          </xs:attribute>
        </xsl:if>
        <xsl:if test="dsrl:attribute-map">
          <xs:for-each select="@*">
            <xsl:call-template name="attribute-map"/>
          </xs:for-each>
          <xsl:for-each select="descendant::dsrl:default-value">
            <xsl:variable name="attribute-name">
              <xsl:if test="../dsrl:name">
                <xsl:value-of select="../dsrl:name"/>
              </xsl:if>
              <xsl:if test="../dsrl:from">
                <xsl:value-of select="../dsrl:from"/>
              </xsl:if>
            </xsl:variable>
            <xsl:variable name="new-attribute-name">
              <xsl:if test="../dsrl:name">
                <xsl:value-of select="../dsrl:name"/>
              </xsl:if>
              <xsl:if test="../dsrl:to">
                <xsl:value-of select="../dsrl:to"/>
              </xsl:if>
            </xsl:variable>
            <xs:if test="not(@{$attribute-name})">
              <xs:attribute name="{$new-attribute-name}">
                <xsl:value-of select="."/>
              </xs:attribute>
            </xs:if>
          </xsl:for-each>
        </xsl:if>
        <xsl:if test="not(dsrl:attribute-map)">
          <xs:apply-templates select="@*"/>
        </xsl:if>
        <xsl:choose>
          <xsl:when test="dsrl:default-content">
            <xs:choose>
              <xs:when test="not(.='')">
                <xs:value-of select="."/>
              </xs:when>
              <xs:otherwise>
                <xsl:value-of select="descendant::dsrl:default-content"/>
              </xs:otherwise>
            </xs:choose>
          </xsl:when>
          <xsl:when test="dsrl:default-content">
            <xs:if test=".=''">
              <!--This only sets the default contents when there is an empty element for the missing element -->
              <xsl:value-of select="dsrl:default-content"/>
            </xs:if>
            <xs:if test="not(.='')">
              <xs:value-of select="."/>
            </xs:if>
          </xsl:when>
          <xsl:otherwise>
            <xs:apply-templates/>
          </xsl:otherwise>
        </xsl:choose>
      </xs:element>
    </xs:template>
    <xsl:if test="dsrl:default-content">
      <xsl:variable name="after" select="dsrl:default-content/@after"/>
      <xsl:variable name="find">
        <xsl:for-each select="//dsrl:element-map/dsrl:to[text()=$after]">
          <xsl:choose>
            <xsl:when test="../dsrl:from">
              <xsl:value-of select="../dsrl:from"/>
            </xsl:when>
            <xsl:when test="../dsrl:name">
              <xsl:value-of select="../dsrl:name"/>
            </xsl:when>
            <xsl:otherwise>
              <xsl:message>Warning: Unable to identify element to be created</xsl:message>
            </xsl:otherwise>
          </xsl:choose>
        </xsl:for-each>
      </xsl:variable>
      <xsl:variable name="within">
        <xsl:value-of select="dsrl:within"/>
      </xsl:variable>
      <xsl:variable name="to">
        <xsl:value-of select="//dsrl:element-map/dsrl:from[.=$within]/following-sibling::dsrl:to[1]"/>
      </xsl:variable>
      <xsl:choose>
        <xsl:when test="$within=''">
          <xsl:message terminate="yes">Error: Must have Within element if default content to be forced</xsl:message>
        </xsl:when>
        <xsl:when test="$within">
          <xsl:if test="not(preceding::dsrl:element-map/dsrl:within)">
            <xsl:text>
            
 </xsl:text>
            <xsl:comment>Higher priority map for <xsl:value-of select="$within"/>
            </xsl:comment>
            <xsl:text>
  </xsl:text>
            <xs:template match="{dsrl:within}" priority="1">
              <xs:element name="{$to}">
                <xs:for-each select="@*">
                  <xsl:for-each select="//dsrl:element-map">
                    <xsl:if test="dsrl:name=$within">
                      <xsl:call-template name="attribute-map"/>
                    </xsl:if>
                    <xsl:if test="dsrl:from=$within">
                      <xsl:call-template name="attribute-map"/>
                    </xsl:if>
                  </xsl:for-each>
                </xs:for-each>
                <xs:apply-templates/>
              </xs:element>
            </xs:template>
          </xsl:if>
        </xsl:when>
        <xsl:otherwise>
          <xsl:message terminate="yes">Error: Must have Within element if default content to be forced</xsl:message>
        </xsl:otherwise>
      </xsl:choose>
      <xsl:text>
       
</xsl:text>
      <xsl:comment>Defines map for <xsl:value-of select="$find"/> when there is no following <xsl:value-of
          select="substring-after($target, '/')"/>. </xsl:comment>
      <xsl:text>
  </xsl:text>
      <xs:template match="{$find}" priority="1">
        <xs:element name="{$after}">
          <xs:for-each select="@*">
            <xsl:for-each select="//dsrl:element-map">
              <xsl:choose>
                <xsl:when test="dsrl:name[.=$find]/following-sibling::dsrl:attribute-map">
                  <xsl:call-template name="attribute-map"/>
                </xsl:when>
                <xsl:when test="dsrl:from[.=$find]/following-sibling::dsrl:attribute-map">
                  <xsl:call-template name="attribute-map"/>
                </xsl:when>
              </xsl:choose>
            </xsl:for-each>
            <xsl:if
              test="not(//dsrl:element-map/dsrl:from[.=$find]/following-sibling::dsrl:attribute-map|//dsrl:element-map/dsrl:name[.=$find]/following-sibling::dsrl:attribute-map)">
              <xs:copy-of select="."/>
            </xsl:if>
          </xs:for-each>
          <xs:apply-templates/>
        </xs:element>
        <xsl:if test="not(substring-after($target, '/'))">
          <xsl:message terminate="yes">Error: Must have Within element if default content is to be forced</xsl:message>
        </xsl:if>
        <xs:if test="not(../{substring-after($target, '/')})">
          <xs:element name="{$new-name}">
            <xsl:for-each select="dsrl:attribute-map">
              <xs:attribute>
                <xsl:attribute name="name">
                  <xsl:if test="dsrl:name">
                    <xsl:value-of select="dsrl:name"/>
                  </xsl:if>
                  <xsl:if test="dsrl:from">
                    <xsl:value-of select="dsrl:to"/>
                  </xsl:if>
                </xsl:attribute>
                <xsl:value-of select="dsrl:default-value"/>
              </xs:attribute>
            </xsl:for-each>
            <xsl:value-of select="dsrl:default-content"/>
          </xs:element>
        </xs:if>
      </xs:template>
    </xsl:if>
  </xsl:template>

  <!--Process free-standing attribute-maps-->
  <xsl:template match="dsrl:maps/dsrl:attribute-map">
    <xsl:variable name="target">
      <xsl:choose>
        <xsl:when test="dsrl:name">
          <xsl:if test="dsrl:within"><xsl:value-of select="dsrl:within"/>/</xsl:if>
          <xsl:text>@</xsl:text>
          <xsl:value-of select="dsrl:name"/>
        </xsl:when>
        <xsl:when test="dsrl:from">
          <xsl:if test="dsrl:within"><xsl:value-of select="dsrl:within"/>/</xsl:if>
          <xsl:text>@</xsl:text>
          <xsl:value-of select="dsrl:from"/>
        </xsl:when>
      </xsl:choose>
    </xsl:variable>
    <xsl:variable name="new-name">
      <xsl:choose>
        <xsl:when test="dsrl:name">
          <xsl:value-of select="dsrl:name"/>
        </xsl:when>
        <xsl:when test="dsrl:to">
          <xsl:value-of select="dsrl:to"/>
        </xsl:when>
        <xsl:when test="dsrl:to-element">element:<xsl:value-of select="dsrl:to-element"/></xsl:when>
      </xsl:choose>
    </xsl:variable>
    <xsl:variable name="within">
      <xsl:value-of select="dsrl:within"/>
    </xsl:variable>
    <xs:template match="{$target}">
      <!--Converts mapped attribute value-->
      <xsl:if test="not(dsrl:to='')">
        <xsl:choose>
          <xsl:when test="contains($new-name, 'element')">
            <xs:element name="{substring-after($new-name, 'element:')}">
              <xsl:call-template name="values-map"/>
              <xsl:choose>
                <xsl:when test="dsrl:default-value and not(dsrl:within)">
                  <xsl:message>Error: Must declare which element default value is to be used within</xsl:message>
                </xsl:when>
              </xsl:choose>
            </xs:element>
          </xsl:when>
          <xsl:otherwise>
            <xs:attribute name="{$new-name}">
              <xsl:call-template name="values-map"/>
            </xs:attribute>
          </xsl:otherwise>
        </xsl:choose>
      </xsl:if>
    </xs:template>
    <xsl:if test="not($within='')">
      <xsl:text>
        
</xsl:text>
      <xs:template match="{$within}" priority="1">
        <xs:element>
          <xsl:attribute name="name">
            <xsl:choose>
              <xsl:when test="//dsrl:element-map/dsrl:from[.=$within]">
                <xsl:value-of select="//dsrl:element-map/dsrl:from[.=$within]/following-sibling::dsrl:to"/>
              </xsl:when>
              <xsl:when test="//dsrl:element-map/dsrl:name[.=$within]">b <xsl:value-of select="$within"/></xsl:when>
            </xsl:choose>
          </xsl:attribute>
          <xs:for-each select="@*[not(name(.)='{substring-after($target, '@')}')]">
            <xsl:for-each select="//dsrl:element-map">
              <xsl:choose>
                <xsl:when test="dsrl:name[.=$within]/following-sibling::dsrl:attribute-map">
                  <xsl:call-template name="attribute-map"/>
                </xsl:when>
                <xsl:when test="dsrl:from[.=$within]/following-sibling::dsrl:attribute-map">
                  <xsl:call-template name="attribute-map"/>
                </xsl:when>
              </xsl:choose>
            </xsl:for-each>
            <xsl:if
              test="not(//dsrl:element-map/dsrl:from[.=$within]/following-sibling::dsrl:attribute-map|//dsrl:element-map/dsrl:name[.=$within]/following-sibling::dsrl:attribute-map)">
              <xs:copy-of select="."/>
            </xsl:if>
          </xs:for-each>
          <xsl:if test="not(contains($new-name, 'element:'))">
            <xs:attribute name="{$new-name}">
              <xs:choose>
                <xs:when test="{substring-after($target, '/')}">
                  <xs:value-of select="{substring-after($target, '/')}"/>
                </xs:when>
                <xs:otherwise>
                  <xsl:value-of select="dsrl:default-value"/>
                </xs:otherwise>
              </xs:choose>
            </xs:attribute>
          </xsl:if>
          <xsl:if test="contains($new-name, 'element:')">
            <xs:element name="{substring-after($new-name, 'element:')}">
              <xs:choose>
                <xs:when test="{substring-after($target, '/')}">
                  <xs:value-of select="{substring-after($target, '/')}"/>
                </xs:when>
                <xs:otherwise>
                  <xsl:value-of select="dsrl:default-value"/>
                </xs:otherwise>
              </xs:choose>
            </xs:element>
          </xsl:if>
          <xs:apply-templates/>
        </xs:element>
      </xs:template>
    </xsl:if>
  </xsl:template>

  <!--Process embedded element maps-->
  <xsl:template name="attribute-map">
    <xs:choose>
      <xsl:for-each select="dsrl:attribute-map">
        <xsl:variable name="attribute-name">
          <xsl:if test="dsrl:name">
            <xsl:value-of select="dsrl:name"/>
          </xsl:if>
          <xsl:if test="dsrl:from">
            <xsl:value-of select="dsrl:from"/>
          </xsl:if>
        </xsl:variable>
        <xsl:variable name="new-element-name">
          <xsl:value-of select="dsrl:to-element"/>
        </xsl:variable>
        <xsl:variable name="new-attribute-name">
          <xsl:if test="dsrl:name">
            <xsl:value-of select="dsrl:name"/>
          </xsl:if>
          <xsl:if test="dsrl:to">
            <xsl:value-of select="dsrl:to"/>
          </xsl:if>
        </xsl:variable>
        <xs:when test="name()='{$attribute-name}'">
          <xsl:if test="not($new-attribute-name='')">
            <xs:attribute name="{$new-attribute-name}">
              <xsl:if test="dsrl:default-value">
                <xs:if test=".=''">
                  <xsl:value-of select="dsrl:default-value"/>
                </xs:if>
                <xs:if test="not(.='')">
                  <xsl:call-template name="values-map"/>
                </xs:if>
              </xsl:if>
              <xsl:if test="not(dsrl:default-value)">
                <xsl:call-template name="values-map"/>
              </xsl:if>
            </xs:attribute>
          </xsl:if>
          <xsl:if test="not($new-element-name='')">
            <xs:element name="{$new-element-name}">
              <xsl:if test="dsrl:default-value">
                <xsl:value-of select="dsrl:default-value"/>
              </xsl:if>
              <xsl:if test="dsrl:default-value">
                <xs:if test=".=''">
                  <xsl:value-of select="dsrl:default-value"/>
                </xs:if>
                <xs:if test="not(.='')">
                  <xsl:call-template name="values-map"/>
                </xs:if>
              </xsl:if>
              <xsl:if test="not(dsrl:default-value)">
                <xsl:call-template name="values-map"/>
              </xsl:if>
            </xs:element>
          </xsl:if>
        </xs:when>
      </xsl:for-each>
      <xs:otherwise>
        <xs:copy-of select="."/>
      </xs:otherwise>
    </xs:choose>
  </xsl:template>

  <!-- Process attribute value maps-->
  <xsl:template name="values-map">
    <xsl:choose>
      <xsl:when test="dsrl:values-map">
        <xs:choose>
          <xsl:for-each select="dsrl:values-map/dsrl:from">
            <xs:when test=".='{.}'">
              <xsl:value-of select="following-sibling::dsrl:to[1]"/>
            </xs:when>
          </xsl:for-each>
          <xs:otherwise>
            <xsl:if test="../dsrl:default-value">
              <xs:value-of select="../dsrl:default-value"/>
            </xsl:if>
            <xsl:if test="not(../dsrl:default-value)">
              <xs:value-of select="."/>
            </xsl:if>
          </xs:otherwise>
        </xs:choose>
      </xsl:when>
      <xsl:otherwise>
        <xs:value-of select="."/>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>

  <!-- Process Processing Instruction maps-->
  <xsl:template match="dsrl:map-pi-target">
    <xsl:for-each select="dsrl:from">
      <xs:template match="processing-instruction('{text()}')">
        <!--Converts names of PI target-->
        <xs:text>
          <xsl:text>
 </xsl:text>
        </xs:text>
        <xs:processing-instruction name="{following-sibling::dsrl:to[1]}">
          <xs:value-of select="."/>
        </xs:processing-instruction>
        <xs:text>

          <xsl:text>
 </xsl:text>
        </xs:text>
      </xs:template>
    </xsl:for-each>
  </xsl:template>

  <!--Process entity name maps-->
  <xsl:template match="dsrl:entity-name-map">
    <xs:template match="text()">
      <!--Converts entity references from one name to another
        Passes from/to name pair to find-entity-ref template for creation of new entity definitions-->
      <xs:call-template name="find-entity-ref">
        <xs:with-param name="t" select="."/>
      </xs:call-template>
    </xs:template>

    <xs:template name="find-entity-ref">
      <!--
      Converts entity references to a validatable form.
       Presumes that all entities mapped to are defined in the relevant document type.
       Remember that when XML schemas are being used for validation only the five
       predefined entities, amp, lt, gt, quot and apos are defined; any other name 
       specified for validation will generate an error.
       -->
      <xs:param name="t"/>
      <xsl:variable name="entities">
        <xsl:for-each select="dsrl:from">
          <xsl:text disable-output-escaping="yes">&#60;</xsl:text>!ENTITY <xsl:value-of select="text()"/>
            "[[entity::<xsl:value-of select="text()"/>]]"<xsl:text disable-output-escaping="yes">&#62;
</xsl:text>
        </xsl:for-each>
        <xsl:for-each select="//dsrl:define-entity">
          <xsl:text disable-output-escaping="yes">&#60;</xsl:text>!ENTITY <xsl:value-of select="dsrl:from"/>
            "[[entity::<xsl:value-of select="dsrl:from"/>]]"
          <xsl:text disable-output-escaping="yes">&#62;
</xsl:text>
        </xsl:for-each>
      </xsl:variable>
      <xsl:result-document href="{$output-directory}{$entity-redefinition}" format="entity-definitions">
        <!--
          This file should be used to update the entity definitions of all mapped 
          entities by adding it to the end of the input DOCTYPE definition.
          Typically this will involve the addition of a parameter entity with 
          the following generalized form:
            &lt;!ENTITY % DSRLentities SYSTEM "DSRLentities.ent"&gt; %DSRLentities;
        -->
        <xsl:value-of select="$entities"/>

      </xsl:result-document>

      <xsl:result-document href="{$output-directory}{$MappedEntities}" format="mapped-entities">
        <!--  
          This file should be used to update the entity definitions of all mapped 
          entities by adding it to the end of the  DOCTYPE definition associated with the transformation stylesheet.
          Typically this will involve the addition of a parameter entity with 
          the following generalized form:
            &lt;!ENTITY % mapped-entities SYSTEM "MappedEntities.ent"&gt; %mapped-entities;
        -->
        <xsl:for-each select="//dsrl:entity-name-map/dsrl:from">
          <xsl:if
            test="not(following-sibling::dsrl:to[1]='amp') and 
                            not(following-sibling::dsrl:to[1]='lt') and 
                            not(following-sibling::dsrl:to[1]='gt') and 
                            not(following-sibling::dsrl:to[1]='apos') and 
                            not(following-sibling::dsrl:to[1]='quot')">
            <xsl:variable name="entity-definition2">[[Need definition for <xsl:value-of
                select="following-sibling::dsrl:to[1]"/> here]]</xsl:variable>
            <xsl:text disable-output-escaping="yes">&#60;</xsl:text>!ENTITY <xsl:value-of
              select="following-sibling::dsrl:to[1]"/> "<xsl:value-of select="$entity-definition2"
            />"<xsl:text disable-output-escaping="yes">&#62;
</xsl:text>
          </xsl:if>
        </xsl:for-each>
        <xsl:for-each select="//dsrl:define-entity">
          <xsl:text disable-output-escaping="yes">&#60;</xsl:text>!ENTITY <xsl:value-of select="dsrl:from"/>
            "<xsl:copy-of select="dsrl:replacement-text/node()"
          />"<xsl:text disable-output-escaping="yes">&#62;
 </xsl:text>
        </xsl:for-each>
      </xsl:result-document>
      <xs:choose>
        <xsl:for-each select="dsrl:from">
          <xsl:variable name="entity-name-entered">
            <xsl:value-of select="text()"/>
          </xsl:variable>
          <xsl:variable name="entity-to-be-validated">
            <xsl:value-of select="following-sibling::dsrl:to[1]"/>
          </xsl:variable>
          <xs:when test="contains($t, '[[entity::{$entity-name-entered}]]')">
            <xs:variable name="starts" select="substring-before($t, '[[entity::{$entity-name-entered}]]')"/>
            <xs:call-template name="find-entity-ref">
              <xs:with-param name="t" select="$starts"/>
            </xs:call-template>
            <xs:text><xsl:text disable-output-escaping="yes">&#38;</xsl:text>
              <xsl:value-of select="$entity-to-be-validated"/>;</xs:text>
            <xs:variable name="ends" select="substring-after($t, '[[entity::{$entity-name-entered}]]')"/>
            <xs:call-template name="find-entity-ref">
              <xs:with-param name="t" select="$ends"/>
            </xs:call-template>
          </xs:when>
        </xsl:for-each>
        <xsl:for-each select="//dsrl:define-entity">
          <xsl:variable name="entity-name-entered">
            <xsl:value-of select="dsrl:from"/>
          </xsl:variable>
          <xsl:variable name="entity-to-be-validated">
            <xsl:value-of select="dsrl:from"/>
          </xsl:variable>
          <xs:when test="contains($t, '[[entity::{$entity-name-entered}]]')">
            <xs:variable name="starts" select="substring-before($t, '[[entity::{$entity-name-entered}]]')"/>
            <xs:call-template name="find-entity-ref">
              <xs:with-param name="t" select="$starts"/>
            </xs:call-template>
            <xsl:text disable-output-escaping="yes">&#38;</xsl:text>
            <xsl:value-of select="$entity-to-be-validated"/>;<xs:variable name="ends"
              select="substring-after($t, '[[entity::{$entity-name-entered}]]')"/>
            <xs:call-template name="find-entity-ref">
              <xs:with-param name="t" select="$ends"/>
            </xs:call-template>
          </xs:when>
        </xsl:for-each>
        <xs:otherwise>
          <xs:value-of select="$t"/>
        </xs:otherwise>
      </xs:choose>
    </xs:template>
  </xsl:template>

  <!--Process entity definitions within DSRL map-->
  <xsl:template match="dsrl:define-entity">
    <!--Entity definitions are mapped as part of entity maps. This empty
    definition ensures that their contents are discarded-->
  </xsl:template>

</xsl:stylesheet>

