bldsystemtools/sysdeftools/mergesysdef-module.xsl
changeset 63 d706e2bc01db
parent 25 85578ba0aa08
equal deleted inserted replaced
51:858432135449 63:d706e2bc01db
    16 <xsl:variable name="defaultnamespace">http://www.symbian.org/system-definition</xsl:variable>
    16 <xsl:variable name="defaultnamespace">http://www.symbian.org/system-definition</xsl:variable>
    17 
    17 
    18 <xsl:template match="/SystemDefinition[starts-with(@schema,'2.') or starts-with(@schema,'1.')]" priority="2" mode="merge-models">
    18 <xsl:template match="/SystemDefinition[starts-with(@schema,'2.') or starts-with(@schema,'1.')]" priority="2" mode="merge-models">
    19 	<xsl:message terminate="yes">ERROR: Syntax <xsl:value-of select="@schema"/> not supported</xsl:message>
    19 	<xsl:message terminate="yes">ERROR: Syntax <xsl:value-of select="@schema"/> not supported</xsl:message>
    20 </xsl:template>
    20 </xsl:template>
    21 <xsl:template match="/SystemDefinition[not(systemModel)]" priority="2" mode="merge-models">
    21 <!--<xsl:template match="/SystemDefinition[not(systemModel)]" priority="2" mode="merge-models">
    22 	<xsl:message terminate="yes">ERROR: Can only merge stand-alone system models</xsl:message>
    22 	<xsl:message terminate="yes">ERROR: Can only merge stand-alone system models</xsl:message>
    23 </xsl:template>
    23 </xsl:template>-->
    24 
    24 
    25 <!-- stuff for dealing with namespaces -->
    25 <!-- stuff for dealing with namespaces -->
    26 
    26 
    27 
    27 
    28 <xsl:template match="node()|@*" mode="translate-namespaces"><xsl:copy-of select="."/></xsl:template>
    28 <xsl:template match="node()|@*" mode="translate-namespaces"><xsl:copy-of select="."/></xsl:template>
    40 </xsl:apply-templates>
    40 </xsl:apply-templates>
    41 </xsl:element>
    41 </xsl:element>
    42 </xsl:template>
    42 </xsl:template>
    43 
    43 
    44 
    44 
    45 <xsl:template match="@id|@before" mode="translate-namespaces"><xsl:param name="nsdoc"/>
    45 <xsl:template match="@id|@before|@replace" mode="translate-namespaces"><xsl:param name="nsdoc"/>
    46 	<xsl:attribute name="{name()}">
    46 	<xsl:attribute name="{name()}">
    47 		<xsl:variable name="id">
    47 		<xsl:variable name="id">
    48 			<xsl:choose>
    48 			<xsl:choose>
    49 				<xsl:when test="contains(.,':')">
    49 				<xsl:when test="contains(.,':')">
    50 					<xsl:value-of select="substring-after(.,':')"/>
    50 					<xsl:value-of select="substring-after(.,':')"/>
    57 		<xsl:variable name="ns">
    57 		<xsl:variable name="ns">
    58 			<xsl:choose>
    58 			<xsl:choose>
    59 				<xsl:when test="contains(.,':')">
    59 				<xsl:when test="contains(.,':')">
    60 					<xsl:value-of select="ancestor-or-self::*/namespace::*[name()=substring-before(current()/.,':')]"/>
    60 					<xsl:value-of select="ancestor-or-self::*/namespace::*[name()=substring-before(current()/.,':')]"/>
    61 				</xsl:when>
    61 				</xsl:when>
    62 				<xsl:when test="/SystemDefinition/@id-namespace">
    62 				<xsl:when test="ancestor::SystemDefinition/@id-namespace">
    63 					<xsl:value-of select="/SystemDefinition/@id-namespace"/>
    63 					<xsl:value-of select="ancestor::SystemDefinition/@id-namespace"/>
    64 				</xsl:when>
    64 				</xsl:when>
    65 				<xsl:otherwise>
    65 				<xsl:otherwise>
    66 					<xsl:value-of select="$defaultnamespace"/>
    66 					<xsl:value-of select="$defaultnamespace"/>
    67 				</xsl:otherwise>
    67 				</xsl:otherwise>
    68 			</xsl:choose>
    68 			</xsl:choose>
    75 				<xsl:value-of select="$id"/>
    75 				<xsl:value-of select="$id"/>
    76 			</xsl:when>
    76 			</xsl:when>
    77 			<xsl:when test="$nsdoc/namespace::*[.=$ns]">
    77 			<xsl:when test="$nsdoc/namespace::*[.=$ns]">
    78 				<xsl:value-of select="concat(name($nsdoc/namespace::*[.=$ns]),':',$id)"/>
    78 				<xsl:value-of select="concat(name($nsdoc/namespace::*[.=$ns]),':',$id)"/>
    79 			</xsl:when>
    79 			</xsl:when>
    80 			<xsl:when test="/SystemDefinition/@id-namespace=$ns">
    80 			<xsl:when test="ancestor::SystemDefinition/@id-namespace=$ns">
    81 				<xsl:variable name="myns">
    81 				<xsl:variable name="myns">
    82 					<xsl:apply-templates mode="ns-prefix" select="$nsdoc">
    82 					<xsl:apply-templates mode="ns-prefix" select="$nsdoc">
    83 						<xsl:with-param name="ns" select="$ns"/>
    83 						<xsl:with-param name="ns" select="$ns"/>
    84 					</xsl:apply-templates>
    84 					</xsl:apply-templates>
    85 				</xsl:variable>			
    85 				</xsl:variable>			
    91 			</xsl:otherwise>
    91 			</xsl:otherwise>
    92 		</xsl:choose>		
    92 		</xsl:choose>		
    93 	</xsl:attribute>
    93 	</xsl:attribute>
    94 </xsl:template>
    94 </xsl:template>
    95 
    95 
    96 <xsl:template match="/SystemDefinition" mode="ns-prefix">
    96 <xsl:template match="SystemDefinition" mode="ns-prefix">
    97 	<xsl:param name="ns"/> <!-- the namespace URI -->
    97 	<xsl:param name="ns"/> <!-- the namespace URI -->
    98 	<xsl:param name="pre"/> <!-- the preferred prefix to use if possbile -->
    98 	<xsl:param name="pre"/> <!-- the preferred prefix to use if possbile -->
    99 	<xsl:param name="dontuse"/> <!-- space prefixed, separated and terminated list of namespace prefixes to not use -->
    99 	<xsl:param name="dontuse"/> <!-- space prefixed, separated and terminated list of namespace prefixes to not use -->
   100 	<xsl:param name="chars">ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz</xsl:param> <!-- single letter namespace prefixes to try -->
   100 	<xsl:param name="chars">ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz</xsl:param> <!-- single letter namespace prefixes to try -->
   101 	<xsl:variable name="name" select="substring(substring-after($ns,'http://www.'),1,1)"/>
   101 	<xsl:variable name="name" select="substring(substring-after($ns,'http://www.'),1,1)"/>
   119 </xsl:template>
   119 </xsl:template>
   120 
   120 
   121 
   121 
   122 <!--  need to make sure this handles <meta> correctly -->
   122 <!--  need to make sure this handles <meta> correctly -->
   123 
   123 
   124 <xsl:template match="/SystemDefinition" mode="merge-models">
   124 <xsl:template match="SystemDefinition" mode="merge-models">
   125 	<xsl:param name="other"/>	<!-- the downstream SystemDefinition this is merged with -->
   125 	<xsl:param name="other"/>	<!-- the downstream SystemDefinition this is merged with -->
   126 	<xsl:param name="up" select="systemModel"/>	<!-- the element containing the origin @name used for any component from "this" model. -->
   126 	<xsl:param name="up" select="systemModel"/>	<!-- the element containing the origin @name used for any component from "this" model. -->
   127 	<xsl:param name="down" select="$other/systemModel"/> <!-- the element containing origin @name used for any component from $other model. -->
   127 	<xsl:param name="down" select="$other/systemModel"/> <!-- the element containing origin @name used for any component from $other model. -->
   128 	
   128 	
   129 	<!-- do some testing -->
   129 	<!-- do some testing -->
   130  	<xsl:if test="$other[starts-with(@schema,'2.') or starts-with(@schema,'1.')]">
   130  	<xsl:if test="$other[starts-with(@schema,'2.') or starts-with(@schema,'1.')]">
   131 		<xsl:message terminate="yes">ERROR: Syntax <xsl:value-of select="$other/@schema"/> not supported</xsl:message>
   131 		<xsl:message terminate="yes">ERROR: Syntax <xsl:value-of select="$other/@schema"/> not supported</xsl:message>
   132 	</xsl:if>
   132 	</xsl:if>
   133 	<xsl:if test="not($other/systemModel)">
   133 	<xsl:if test="name(*) != name($other/*)">
   134 		<xsl:message terminate="yes">ERROR: Can only merge stand-alone system models</xsl:message>
   134 		<xsl:message terminate="yes">ERROR: Can only merge system models of the same rank</xsl:message>
   135 	</xsl:if>
   135 	</xsl:if>
   136 	 
   136 	 
   137 	<xsl:copy>
   137 	<xsl:copy>
   138 		<xsl:copy-of  select="@*"/> <!--  use attributes from origin model -->
   138 		<xsl:attribute name="schema">
       
   139 			<xsl:call-template name="compare-versions">
       
   140 				<xsl:with-param name="v1" select="@schema"/>
       
   141 				<xsl:with-param name="v2" select="$other/@schema"/>
       
   142 			</xsl:call-template>
       
   143 		</xsl:attribute>
       
   144 		<xsl:copy-of  select="@*[name()!='schema']"/> <!--  use attributes from origin model -->
   139 		<xsl:variable name="namespaces">
   145 		<xsl:variable name="namespaces">
   140 			<xsl:copy> <!-- needs <copy> so the processor doesn't lose the namespaces -->
   146 			<xsl:copy> <!-- needs <copy> so the processor doesn't lose the namespaces -->
   141 				<!--copy namespaces as needed -->
   147 				<!--copy namespaces as needed -->
   142 				
   148 				
   143 				<xsl:copy-of select="namespace::*[name()!='xml']"/> <!-- all upstream namespaces -->
   149 				<xsl:copy-of select="namespace::*[name()!='xml']"/> <!-- all upstream namespaces -->
   181 	</xsl:variable>
   187 	</xsl:variable>
   182 		<xsl:apply-templates mode="merge-models">
   188 		<xsl:apply-templates mode="merge-models">
   183 			<xsl:with-param name="other" select="exslt:node-set($otherdoc)/*"/>
   189 			<xsl:with-param name="other" select="exslt:node-set($otherdoc)/*"/>
   184 			<xsl:with-param name="up" select="$up"/>
   190 			<xsl:with-param name="up" select="$up"/>
   185 			<xsl:with-param name="down" select="$down"/>
   191 			<xsl:with-param name="down" select="$down"/>
       
   192 			<xsl:with-param name="replaces" select="exslt:node-set($otherdoc)//*[self::component or self::collection or self::package or self::layer]/@replace"/>
   186 		</xsl:apply-templates>
   193 		</xsl:apply-templates>
   187 	
   194 	
   188 	</xsl:copy>
   195 	</xsl:copy>
   189 </xsl:template>
   196 </xsl:template>
   190 
   197 
   191 <xsl:template match="systemModel" mode="merge-models">
   198 <xsl:template match="systemModel" mode="merge-models">
   192 	<xsl:param name="other"/>	<!-- the parent of the downstream systemModel this is merged with -->
   199 	<xsl:param name="other"/>	<!-- the parent of the downstream systemModel this is merged with -->
   193 	<xsl:param name="up"/>
   200 	<xsl:param name="up"/>
   194 	<xsl:param name="down"/>
   201 	<xsl:param name="down"/>
       
   202 	<xsl:param name="replaces"/>
   195 	<xsl:copy><xsl:copy-of  select="@*"/>
   203 	<xsl:copy><xsl:copy-of  select="@*"/>
   196 		<!--  copy metas and comments in between meta. Do not try to merge metadata between models -->
   204 		<!--  copy metas and comments in between meta. Do not try to merge metadata between models -->
   197 			<xsl:copy-of select="meta | $other/systemModel/meta | comment()[following-sibling::meta]"/>	
   205 			<xsl:copy-of select="meta | $other/systemModel/meta | comment()[following-sibling::meta]"/>	
   198 		<xsl:apply-templates mode="merge-models">
   206 		<xsl:apply-templates mode="merge-models">
   199 			<xsl:with-param name="other" select="$other/systemModel"/>
   207 			<xsl:with-param name="other" select="$other/systemModel"/>
   200 			<xsl:with-param name="up" select="$up"/>
   208 			<xsl:with-param name="up" select="$up"/>
   201 			<xsl:with-param name="down" select="$down"/>
   209 			<xsl:with-param name="down" select="$down"/>
       
   210 			<xsl:with-param name="replaces" select="$replaces"/>
   202 		</xsl:apply-templates>
   211 		</xsl:apply-templates>
   203 	</xsl:copy>
   212 	</xsl:copy>
   204 </xsl:template>
   213 </xsl:template>
   205 
   214 
   206 <xsl:template match="@*|*|comment()" mode="merge-models"><xsl:copy-of select="."/></xsl:template>
   215 <xsl:template match="@*|*|comment()" mode="merge-models"><xsl:copy-of select="."/></xsl:template>
   224 		<xsl:when test="contains(concat(' ',normalize-space($other/@levels),' '),concat(' ',normalize-space(.),' '))">
   233 		<xsl:when test="contains(concat(' ',normalize-space($other/@levels),' '),concat(' ',normalize-space(.),' '))">
   225 			<!--  If this is contained is other, then use other-->
   234 			<!--  If this is contained is other, then use other-->
   226 			<xsl:copy-of select="$other/@levels"/>
   235 			<xsl:copy-of select="$other/@levels"/>
   227 		</xsl:when>
   236 		</xsl:when>
   228 		<xsl:when test="contains(concat(' ',normalize-space($other/@levels),' '),' - ')">
   237 		<xsl:when test="contains(concat(' ',normalize-space($other/@levels),' '),' - ')">
   229 			<!-- if other uses + syntax, then pre/append -->
   238 			<!-- if other uses - syntax, then pre/append -->
   230 			<xsl:variable name="lev">
   239 			<xsl:variable name="lev">
   231 				<xsl:value-of select="substring-before(concat(' ',normalize-space($other/@levels),' '),' - ')"/>
   240 				<xsl:value-of select="substring-before(concat(' ',normalize-space($other/@levels),' '),' - ')"/>
   232 				<xsl:value-of select="concat(' ',.,' ')"/>
   241 				<xsl:value-of select="concat(' ',.,' ')"/>
   233 				<xsl:value-of select="substring-after(concat(' ',normalize-space($other/@levels),' '),' - ')"/>
   242 				<xsl:value-of select="substring-after(concat(' ',normalize-space($other/@levels),' '),' - ')"/>
   234 			</xsl:variable>
   243 			</xsl:variable>
   314 			</xsl:call-template>
   323 			</xsl:call-template>
   315 		</xsl:when>	
   324 		</xsl:when>	
   316 	</xsl:choose>
   325 	</xsl:choose>
   317 </xsl:template>
   326 </xsl:template>
   318 
   327 
       
   328 <xsl:template match="node()" mode="merge-data">
       
   329 	<xsl:copy-of select="." />
       
   330 </xsl:template>
       
   331 
       
   332 <xsl:template match="meta" mode="merge-data">
       
   333 	<xsl:param name="metas" />
       
   334 	<!-- compare this meta against all metas in the  merged doc
       
   335 		if they are identical, then ignore this one.
       
   336 		identical is computed by translating to a string, normalising some known parts. This might be slow in some cases-->
       
   337 	<xsl:variable name="val"><xsl:apply-templates select="." mode="as-xml-text" /></xsl:variable>
       
   338 	<xsl:variable name="match">
       
   339 		<xsl:for-each select="$metas">
       
   340 			<xsl:variable name="cur"><xsl:apply-templates select="." mode="as-xml-text" /></xsl:variable>
       
   341 			<xsl:if test="$cur=$val">*</xsl:if>
       
   342 		</xsl:for-each>
       
   343 	</xsl:variable>
       
   344 	<xsl:if test="$match='' ">
       
   345 		<xsl:copy-of select="." />
       
   346 	</xsl:if>
       
   347 </xsl:template>
       
   348 
       
   349 <xsl:template match="text()[normalize-space(.)='']" mode="as-xml-text"/>
       
   350 <xsl:template match="node()" mode="as-xml-text"><xsl:value-of select="."/></xsl:template>
       
   351 <xsl:template match="comment()" mode="as-xml-text">&lt;--<xsl:value-of select="."/>--&gt;</xsl:template>
       
   352 <xsl:template match="@*" mode="as-xml-text">
       
   353 	<xsl:value-of select="concat(' ',name())"/>="<xsl:value-of select="."/>"</xsl:template>
       
   354 <xsl:template match="*" mode="as-xml-text">
       
   355 	<xsl:value-of select="concat('&lt;',name())"/>
       
   356 	<xsl:apply-templates select="@*" mode="as-xml-text"/>
       
   357 	<xsl:if test="self::meta and not(@rel)"> rel="Generic"</xsl:if>
       
   358 	<xsl:if test="self::meta and not(@type)"> type="auto"</xsl:if>
       
   359 	<xsl:text>&gt;</xsl:text>
       
   360 	<xsl:apply-templates select="node()" mode="as-xml-text"/>
       
   361 	<xsl:value-of select="concat('&lt;/',name(),'&gt;')"/>
       
   362 </xsl:template>
       
   363 
       
   364 
   319 <xsl:template match="layer | package | collection | component" mode="merge-models">
   365 <xsl:template match="layer | package | collection | component" mode="merge-models">
   320 	<xsl:param name="other"/>	<!-- the downstream item of the parent's rank that contains a potential items this is merged with -->
   366 	<xsl:param name="other"/>	<!-- the downstream item of the parent's rank that contains a potential items this is merged with -->
   321 	<xsl:param name="up"/>
   367 	<xsl:param name="up"/>
   322 	<xsl:param name="down"/>
   368 	<xsl:param name="down"/>
       
   369 	<xsl:param name="replaces"/>
   323 	<xsl:variable name="this" select="."/>	<!-- current item -->
   370 	<xsl:variable name="this" select="."/>	<!-- current item -->
   324 	
   371 
   325 	<!-- match = this item in the downstream model -->	
   372 	<!-- match = this item in the downstream model -->	
   326 	<xsl:variable name="match" select="$other/*[@id=current()/@id]"/>
   373 	<xsl:variable name="match" select="$other/*[@id=current()/@id]"/>
   327 	
   374 
       
   375 	<xsl:choose>
       
   376 		<xsl:when test="$replaces[.=$this/@id] or (self::component and $match)">  <!-- replace the item instead of merge -->
       
   377 			<xsl:message>Note: <xsl:value-of select="name()"/> "<xsl:value-of select="@id"/>" <xsl:choose>
       
   378 				<xsl:when test="self::component and $match">overridden in downstream sysdef</xsl:when>
       
   379 				<xsl:otherwise><xsl:for-each select="$replaces[.=$this/@id]/..">replaced by <xsl:value-of select="name()"/> "<xsl:value-of select="@id"/>"</xsl:for-each></xsl:otherwise>
       
   380 			</xsl:choose>
       
   381 			</xsl:message>
       
   382 			<!-- if the removed item is in the downstream doc, just copy that and ignore the upstream contents -->
       
   383 			<xsl:apply-templates mode="merge-copy-of" select="$match">
       
   384 				<xsl:with-param name="origin" select="$down"/>
       
   385 				<xsl:with-param name="root" select="$this/ancestor::systemModel"/>			
       
   386 			</xsl:apply-templates>		
       
   387 		</xsl:when>
       
   388 		<xsl:otherwise>
       
   389 			<!-- remove this if it's in the list of stuff to be replaced-->
       
   390 
   328 	<!-- prev = the previous item before the current one (no metas, only named items)-->
   391 	<!-- prev = the previous item before the current one (no metas, only named items)-->
   329 	<xsl:variable name="prev" select="preceding-sibling::*[@id][1]"/> 
   392 	<xsl:variable name="prev" select="preceding-sibling::*[@id][1]"/> 
   330 
   393 
   331 	<!-- copy all items between this and prev  that are solely in the downstream model -->	 		
   394 	<!-- copy all items between this and prev  that are solely in the downstream model -->	 		
   332 
   395 
   370 			<xsl:if test="not(@root)">
   433 			<xsl:if test="not(@root)">
   371 				<xsl:copy-of select="$up/@root"/>
   434 				<xsl:copy-of select="$up/@root"/>
   372 			</xsl:if>
   435 			</xsl:if>
   373 		</xsl:if>
   436 		</xsl:if>
   374 		
   437 		
   375 		<xsl:for-each select="$match/@*">  <!-- copy downstream attributes, only if not set on upstream -->
   438 		<xsl:for-each select="$match/@*[name()!='replace']">  <!-- copy downstream attributes, only if not set on upstream -->
   376 			<xsl:if test="not($this/@*[name()=name(current())])"><xsl:copy-of select="."/></xsl:if>
   439 			<xsl:if test="not($this/@*[name()=name(current())])"><xsl:copy-of select="."/></xsl:if>
   377 		</xsl:for-each>
   440 		</xsl:for-each>
       
   441 
       
   442 		<xsl:if test="$match/@replace"> <!-- check replace separately -->
       
   443 			<xsl:if test="not($this/ancestor::SystemDefinition//*[(self::component or self::collection or self::package or self::layer) and $match/@replace=@id])">
       
   444 				<!-- only remove replace if it's been used -->
       
   445 				<xsl:copy-of select="$match/@replace"/>
       
   446 			</xsl:if>
       
   447 		</xsl:if>
   378 		
   448 		
   379 		<xsl:choose>
   449 		<xsl:choose>
   380 			<xsl:when test="self::component">
   450 			<xsl:when test="self::component">
   381 				<!-- copy all units, metas and comments from this
   451 				<!-- copy all units, metas and comments from this
   382 					copy all metas in the merged component
   452 					copy all metas in the merged component
   386 				<xsl:copy-of select="*|comment() | $match/meta |$match/unit[not($this/unit)] | $match/unit[$this/unit and @version[.!=$this/unit/@version]] | $match/comment()[.!=$this/comment()]"/>				
   456 				<xsl:copy-of select="*|comment() | $match/meta |$match/unit[not($this/unit)] | $match/unit[$this/unit and @version[.!=$this/unit/@version]] | $match/comment()[.!=$this/comment()]"/>				
   387 			</xsl:when>
   457 			</xsl:when>
   388 			<xsl:otherwise>
   458 			<xsl:otherwise>
   389 
   459 
   390 				<!--  copy metas and comments in between meta. Do not try to merge metadata between models -->
   460 				<!--  copy metas and comments in between meta. Do not try to merge metadata between models -->
   391 				<xsl:copy-of select="meta | $match/meta | comment()[following-sibling::meta]"/>
   461 				<xsl:apply-templates select="meta | $match/meta | comment()[following-sibling::meta]" mode="merge-data">
       
   462 					<xsl:with-param name="metas" select="$match/meta"/>
       
   463 				</xsl:apply-templates>
       
   464 				<xsl:copy-of select=" $match/meta | $match/comment()[following-sibling::meta]"/>
   392 				
   465 				
   393 				<xsl:apply-templates mode="merge-models">
   466 				<xsl:apply-templates mode="merge-models">
   394 					<xsl:with-param name="other" select="$match"/>
   467 					<xsl:with-param name="other" select="$match"/>
   395 					<xsl:with-param name="up" select="$up"/>
   468 					<xsl:with-param name="up" select="$up"/>
   396 					<xsl:with-param name="down" select="$down"/>
   469 					<xsl:with-param name="down" select="$down"/>
       
   470 					<xsl:with-param name="replaces" select="$replaces"/>
   397 				</xsl:apply-templates>
   471 				</xsl:apply-templates>
   398 				<!--  don't copy if explicitly or implicitly placed already-->
   472 				<!--  don't copy if explicitly or implicitly placed already-->
   399 				<xsl:for-each select="$match/*[not(@before) and not(following-sibling::*[@id=$this/*/@id])]">
   473 				<xsl:for-each select="$match/*[not(@before) and not(following-sibling::*[@id=$this/*/@id])]">
   400 					<xsl:if test="not($this/*[@id=current()/@id])">
   474 					<xsl:if test="not($this/*[@id=current()/@id])">
   401 						<xsl:apply-templates mode="merge-copy-of" select=".">
   475 						<xsl:apply-templates mode="merge-copy-of" select=".">
   405 					</xsl:if>
   479 					</xsl:if>
   406 				</xsl:for-each>
   480 				</xsl:for-each>
   407 			</xsl:otherwise>
   481 			</xsl:otherwise>
   408 		</xsl:choose>
   482 		</xsl:choose>
   409 	</xsl:copy>
   483 	</xsl:copy>
       
   484 
       
   485 		</xsl:otherwise>
       
   486 	</xsl:choose>
   410 	
   487 	
   411 	<xsl:if test="self::layer and not(following-sibling::layer)">
   488 	<xsl:if test="self::layer and not(following-sibling::layer)">	
   412 		<!-- for the last layer, tack on any remaining layers -->
   489 		<!-- for the last layer, tack on any remaining layers -->
   413 		<xsl:apply-templates mode="merge-copy-of" select="$other/layer[not(@before) and not(following-sibling::*[@id=$this/../layer/@id]) and not(@id=$this/../layer/@id)]">
   490 		<xsl:apply-templates mode="merge-copy-of" select="$other/layer[not(@before) and not(following-sibling::*[@id=$this/../layer/@id]) and not(@id=$this/../layer/@id)]">
   414 			<xsl:with-param name="origin" select="$down"/>
   491 			<xsl:with-param name="origin" select="$down"/>
   415 			<xsl:with-param name="root" select="$this/ancestor::systemModel"/>			
   492 			<xsl:with-param name="root" select="$this/ancestor::systemModel"/>			
   416 		</xsl:apply-templates>		
   493 		</xsl:apply-templates>		
   446 						<xsl:text>&#xa;</xsl:text>
   523 						<xsl:text>&#xa;</xsl:text>
   447 					</xsl:message>
   524 					</xsl:message>
   448 				</xsl:when>
   525 				</xsl:when>
   449 				<xsl:otherwise>
   526 				<xsl:otherwise>
   450 					<xsl:copy>
   527 					<xsl:copy>
   451 						<xsl:choose>
   528 						<xsl:call-template name="merge-copy-of-atts">
   452 							<xsl:when test="$remove-before">
   529 							<xsl:with-param name="remove-before" select="$remove-before"/>
   453 								<xsl:copy-of select="@*[name()!='before']"/>
   530 							<xsl:with-param name="root" select="$root"/>
   454 							</xsl:when>
   531 						</xsl:call-template>
   455 							<xsl:otherwise><xsl:copy-of select="@*"/></xsl:otherwise>
       
   456 						</xsl:choose>
       
   457 						<xsl:copy-of select="exslt:node-set($content)"/>
   532 						<xsl:copy-of select="exslt:node-set($content)"/>
   458 					</xsl:copy>
   533 					</xsl:copy>
   459 				</xsl:otherwise>
   534 				</xsl:otherwise>
   460 			</xsl:choose>					
   535 			</xsl:choose>					
   461 		</xsl:otherwise>
   536 		</xsl:otherwise>
   465 
   540 
   466 <xsl:template match="comment()|@*" mode="merge-copy-of">
   541 <xsl:template match="comment()|@*" mode="merge-copy-of">
   467 	<xsl:copy-of select="."/>
   542 	<xsl:copy-of select="."/>
   468 </xsl:template>
   543 </xsl:template>
   469 
   544 
       
   545 
       
   546 <xsl:template name="merge-copy-of-atts">
       
   547 	<xsl:param name="remove-before" select="0"/> <!-- set to true if any before attribute is to be removed -->
       
   548 	<xsl:param name="root"/> 	<!--the systemModel element in the upstream doc  -->
       
   549 	<xsl:choose>
       
   550 		<xsl:when test="$remove-before">
       
   551 			<xsl:copy-of select="@*[name()!='before' and name()!='replace']"/>
       
   552 		</xsl:when>
       
   553 		<xsl:otherwise><xsl:copy-of select="@*[name()!='replace']"/></xsl:otherwise>
       
   554 	</xsl:choose>
       
   555 	<xsl:if test="@replace and not($root/descendant::*[(self::component or self::collection or self::package or self::layer) and @id=current()/@replace])">
       
   556 		<!-- only include replace if it's not been used -->
       
   557 		<xsl:copy-of select="@replace"/>
       
   558 	</xsl:if>
       
   559 </xsl:template>
       
   560 
   470 <xsl:template match="component" mode="merge-copy-of">
   561 <xsl:template match="component" mode="merge-copy-of">
   471 	<xsl:param name="remove-before" select="0"/> <!-- set to true if any before attribute is to be removed -->
   562 	<xsl:param name="remove-before" select="0"/> <!-- set to true if any before attribute is to be removed -->
   472 	<xsl:param name="origin"/>	<!--the element containing the @name to use the origin-model attribute  -->
   563 	<xsl:param name="origin"/>	<!--the element containing the @name to use the origin-model attribute  -->
   473 	<xsl:param name="root"/> 	<!--the systemModel element in the upstream doc  -->
   564 	<xsl:param name="root"/> 	<!--the systemModel element in the upstream doc  -->
   474 	
   565 
   475 	<xsl:choose>
   566 	<xsl:choose>
   476 		<!-- this might slow things down, consider making optional -->
   567 		<!-- this might slow things down, consider making optional -->
   477 		<xsl:when test="$root/descendant::collection[@id!=current()/../@id]/component[@id=current()/@id]">
   568 		<xsl:when test="$root/descendant::collection[@id!=current()/../@id]/component[@id=current()/@id]">
   478 			<xsl:message>Warning: <xsl:value-of select="name()"/> "<xsl:value-of select="@id"/>" moved in downstream model. Ignoring moved <xsl:value-of select="name()"/>
   569 			<xsl:message>Warning: <xsl:value-of select="name()"/> "<xsl:value-of select="@id"/>" moved in downstream model. Ignoring moved <xsl:value-of select="name()"/>
   479 				<xsl:text>&#xa;</xsl:text>
   570 				<xsl:text>&#xa;</xsl:text>
   480 			</xsl:message>
   571 			</xsl:message>
   481 		</xsl:when>
   572 		</xsl:when>
   482 		<xsl:otherwise>
   573 		<xsl:otherwise>
   483 			<xsl:copy>
   574 			<xsl:copy>
   484 				<xsl:choose>
   575 				<xsl:call-template name="merge-copy-of-atts">
   485 					<xsl:when test="$remove-before">
   576 					<xsl:with-param name="remove-before" select="$remove-before"/>
   486 						<xsl:copy-of select="@*[name()!='before']"/>
   577 					<xsl:with-param name="root" select="$root"/>
   487 					</xsl:when>
   578 				</xsl:call-template>
   488 					<xsl:otherwise><xsl:copy-of select="@*"/></xsl:otherwise>
       
   489 				</xsl:choose>
       
   490 				<xsl:if test="not(@origin-model) and $origin/@name">
   579 				<xsl:if test="not(@origin-model) and $origin/@name">
   491 					<xsl:attribute name="origin-model">
   580 					<xsl:attribute name="origin-model">
   492 						<xsl:value-of select="$origin/@name"/>
   581 						<xsl:value-of select="$origin/@name"/>
   493 					</xsl:attribute>
   582 					</xsl:attribute>
   494 					<xsl:if test="not(@root)">
   583 					<xsl:if test="not(@root)">