System model generator bug fixes for merging and dependencies. Support for 3.0.1 syntax. Catch up with sysdeftools. HighFidelityModel
authorBob Rosenberg <bob.rosenberg@nokia.com>
Tue, 28 Sep 2010 17:48:51 +0100
branchHighFidelityModel
changeset 432 0f44a943faf9
parent 429 cb270197b394
child 435 4067ae46bbeb
System model generator bug fixes for merging and dependencies. Support for 3.0.1 syntax. Catch up with sysdeftools.
sysmodelgen/core/draw-model.xsl
sysmodelgen/core/draw.xsl
sysmodelgen/core/joinsysdef-module.xsl
sysmodelgen/core/joinsysdef.xsl
sysmodelgen/core/mergesysdef-module.xsl
sysmodelgen/core/mergesysdef.xsl
sysmodelgen/core/path-module.xsl
sysmodelgen/extra/dependencies.xsl
sysmodelgen/rsc/ModelTemplate.xml
sysmodelgen/src/SysModelGen.pm
--- a/sysmodelgen/core/draw-model.xsl	Wed Sep 22 13:41:43 2010 +0100
+++ b/sysmodelgen/core/draw-model.xsl	Tue Sep 28 17:48:51 2010 +0100
@@ -343,6 +343,7 @@
 	<xsl:for-each select="exslt:node-set($layers)/layer">
 		<xsl:copy><xsl:copy-of select="@id|@span"/>
 			<xsl:choose>
+				<xsl:when test="0"/> <!-- why? was something removed or should something be here?-->
 				<xsl:otherwise> <!-- layers smaller than spanned -->
 					<xsl:choose>
 						<xsl:when test="$spanning[@id=current()/@id] and $span/@height &gt; $h">
@@ -763,7 +764,6 @@
 	<xsl:variable name="content">
 		<xsl:apply-templates mode="sizing"/>
 	</xsl:variable>
-
 	<!-- if there's no content, only show if forced to by placeholder-detail -->
 	<xsl:if test="/SystemDefinition[@placeholder-detail='package' or @placeholder-detail='component' or @placeholder-detail='collection'] 
 		or exslt:node-set($content)/*[self::package or self::collection]">  	
--- a/sysmodelgen/core/draw.xsl	Wed Sep 22 13:41:43 2010 +0100
+++ b/sysmodelgen/core/draw.xsl	Tue Sep 28 17:48:51 2010 +0100
@@ -28,7 +28,9 @@
 			 <v>7.0</v> <v>7.0s</v>
 			 <v>8.0</v> <v>8.0a 8.0b</v><v>8.1 8.1a 8.1b</v>
 			 <v>9.0</v> <v>9.1</v> <v>9.2</v> <v>9.3</v> 
-			 <v>9.4 ^1</v><v>tb91 ^2</v> <v>tb92 9.5 ^3</v> <v>tb101 9.6 ^4</v> <v>Future</v>
+			 <v>9.4 ^1</v><v>tb91 ^2</v> <v>tb92 9.5 ^3</v> <v>tb101 9.6 ^4</v> 
+			 <v>^5</v> <v>^6</v> <v>^7</v> <v>^8</v> <v>^9</v> <v>^10</v>
+			 <v>Future</v>
 		</xsl:otherwise>
 	</xsl:choose>
 </xsl:variable>
--- a/sysmodelgen/core/joinsysdef-module.xsl	Wed Sep 22 13:41:43 2010 +0100
+++ b/sysmodelgen/core/joinsysdef-module.xsl	Tue Sep 28 17:48:51 2010 +0100
@@ -20,7 +20,14 @@
 <!-- create a stand-alone sysdef from a linked set of fragments -->
 
 <xsl:template match="/*" mode="join">
-	<xsl:message terminate="yes">ERROR: Cannot process this document</xsl:message>
+	<xsl:param name="filename"/>
+	<xsl:message terminate="yes">ERROR: Cannot process this document<xsl:if test="$filename !=''"> (<xsl:value-of select="$filename"/>)</xsl:if>
+		<xsl:choose>
+			<xsl:when test="self::SystemDefinition/@schema">. Unrecognised syntax schema="<xsl:value-of select="@schema"/>"</xsl:when>
+			<xsl:when test="self::SystemDefinition">. Missing schema</xsl:when>
+			<xsl:otherwise>. Invalid file type: <xsl:value-of select="name()"/></xsl:otherwise>
+		</xsl:choose>
+	</xsl:message>
 </xsl:template>
 
 <!-- anything in schemas 3.0.x won't add new functional attributes that need processing here, just blindly copy them-->
@@ -47,7 +54,7 @@
 					<xsl:choose>
 						<xsl:when test="$n='id'"/> <!-- never copy this, always set -->
 						<xsl:when test="$origin/@*[name()=$n]"> <!-- don't copy if already set -->
-							<xsl:message>Cannot set "<xsl:value-of select="$n"/>", already set</xsl:message>
+							<xsl:message>Note: Cannot set "<xsl:value-of select="$n"/>", already set on <xsl:value-of select="$origin/@id"/>. Ignoring linked value</xsl:message>
 						</xsl:when>
 						<xsl:when test="$n='before' or $n='replace'">
 							<!-- ensure ns is correct (if any future attribtues will ever use an ID, process it here too)-->
@@ -126,19 +133,23 @@
 <xsl:template match="*[@href and not(self::meta)]" mode="scan-for-namespaces">
 	<!-- produce a list of namespace-prefix namespace pairs separated by newlines, in reverse order found in documents 
 		reverse order so we can try to use the first namespace prefix defined if it's available-->
-	<xsl:for-each select="document(@href,.)/*">
+	<xsl:variable name="linked" select="document(@href,.)/*"/>
+	<xsl:for-each select="$linked">
 		<xsl:apply-templates select="//*[(self::component or self::collection or self::package or self::layer) and @href]" mode="scan-for-namespaces"/>
 		<xsl:for-each select="//namespace::*[.!='http://www.w3.org/XML/1998/namespace'] | @id-namespace">
 			<!-- ignore XML namespace -->
 			<xsl:value-of select="concat(name(),' ',.,'&#xa;')"/>
 		</xsl:for-each>
-	</xsl:for-each>			
+	</xsl:for-each>
+	<xsl:if test="not($linked)">
+	<xsl:message>Note: The link to <xsl:value-of select="@href"/> from <xsl:value-of select="concat(name(),' ',@id)"/> could not be resolved. Perhaps there's an error in the XML?</xsl:message>
+	</xsl:if>
 </xsl:template>
 
 <xsl:template name="needed-namespaces">
 	<xsl:param name="foundns"/>
 	<xsl:param name="usedpre"/>
-	
+
 	<xsl:if test="$foundns!=''">
 		<xsl:variable name="line" select="substring-before($foundns,'&#xa;')"/> <!-- always has trailing newline -->
 		<xsl:variable name="name" select="substring-after($line,' ')"/> <!-- namespace prefix -->
@@ -205,7 +216,8 @@
 
 <xsl:template name="compare-versions"><xsl:param name="v1"/><xsl:param name="v2"/>
 			<xsl:choose>
-				<xsl:when test="$v1=$v2"><xsl:value-of select="$v1"/></xsl:when>
+				<xsl:when test="$v1=''"><xsl:value-of select="$v2"/></xsl:when>
+				<xsl:when test="$v1=$v2 or $v2=''"><xsl:value-of select="$v1"/></xsl:when>
 				<xsl:when test="substring-before($v1,'.') &gt; substring-before($v2,'.')"><xsl:value-of select="$v1"/></xsl:when>
 				<xsl:when test="substring-before($v1,'.') &lt; substring-before($v2,'.')"><xsl:value-of select="$v2"/></xsl:when>
 				<xsl:when test="substring-before(substring-after($v1,'.'),'.') &gt; substring-before(substring-after($v2,'.'),'.')"><xsl:value-of select="$v1"/></xsl:when>
@@ -320,6 +332,7 @@
 				<xsl:with-param name="data" select="$data"/>
 			</xsl:apply-templates>
 		 </xsl:variable>
+	 		 
 		<xsl:element name="{name()}"> <!-- use this instead of <copy> so xalan doesn't add extra wrong namespaces -->
 			<xsl:apply-templates select="@*" mode="join">
 				<xsl:with-param name="namespaces" select="$namespaces"/>
@@ -451,11 +464,9 @@
 		<xsl:text>&#xa;</xsl:text>
 		</xsl:message>
 	</xsl:if>
-
 	<xsl:variable name="prefix" select="name($namespaces[.=$ns])"/>
 	<xsl:attribute name="{name()}">
 	<xsl:choose>
-
 		<xsl:when test="$prefix = 'id-namespace' or  (not($namespaces[name()='id-namespace']) and $ns=$defaultns)"/> <!-- it's the default namespace, no prefix -->
 		<xsl:when test="$prefix='' and contains(.,':')">
 			<!-- complex: copy id and copy namespace (namespace should be copied already)-->
@@ -479,95 +490,7 @@
 <xsl:template match="@*|comment()" mode="join"><xsl:copy-of select="."/></xsl:template>
 
 
-<!-- path handling follows -->
-
- <xsl:template name="lastbefore"><xsl:param name="string"/><xsl:param name="substr" select="'/'"/>
-        <xsl:if test="contains($string,$substr)">
-                <xsl:value-of select="substring-before($string,$substr)"/>
-                <xsl:if test="contains(substring-after($string,$substr),$substr)">
-	                <xsl:value-of select="$substr"/>
-	              </xsl:if>
-        <xsl:call-template name="lastbefore">
-                <xsl:with-param name="string" select="substring-after($string,$substr)"/>
-                <xsl:with-param name="substr" select="$substr"/>
-        </xsl:call-template>
-        </xsl:if>
-</xsl:template>
-
- <xsl:template name="joinpath"><xsl:param name="file"/><xsl:param name="rel"/>
-	<xsl:choose>
-		<xsl:when test="(contains($rel,'://') and not(contains(substring-before($rel,'://'),'/'))) or starts-with($rel,'/')"> <!-- absolute URI or absolute path-->
-			<xsl:value-of select="$rel"/>
-		</xsl:when>
-		<xsl:otherwise> <!-- relative link -->
-			<xsl:call-template name="reducepath">
-				<xsl:with-param name="file">
-					<xsl:call-template name="lastbefore">
-						<xsl:with-param name="string" select="$file"/>
-					</xsl:call-template>
-					<xsl:text>/</xsl:text>
-					<xsl:value-of select="$rel"/>
-				</xsl:with-param>
-			</xsl:call-template>
-		</xsl:otherwise>
-	</xsl:choose>
- </xsl:template>
-
-<xsl:template name="reducepath"><xsl:param name="file"/>
-	<xsl:call-template name="reducedotdotpath">
-    	<xsl:with-param name="file">
-			<xsl:call-template name="reducedotpath">
-		    	<xsl:with-param name="file" select="$file"/>
-		    </xsl:call-template>
-		</xsl:with-param>
-	</xsl:call-template>
-</xsl:template>
-
-<xsl:template name="reducedotdotpath"><xsl:param name="file"/>
-	<xsl:choose>
-		<xsl:when test="starts-with($file,'../')">
-			<xsl:text>../</xsl:text>
-			<xsl:call-template name="reducedotdotpath">
-        		<xsl:with-param name="file" select="substring($file,4)"/>
-			</xsl:call-template>
-		</xsl:when>
-		<xsl:when test="contains($file,'/../')">							
-			<xsl:call-template name="reducepath">
-        		<xsl:with-param name="file">
-			        <xsl:call-template name="lastbefore">
-			                <xsl:with-param name="string" select="substring-before($file,'/../')"/>
-			        </xsl:call-template>
-			        <xsl:text>/</xsl:text>
-					<xsl:value-of select="substring-after($file,'/../')"/>
-				</xsl:with-param>
-			</xsl:call-template>
-		</xsl:when>
-		<xsl:otherwise><xsl:value-of select="$file"/></xsl:otherwise>
-	</xsl:choose>
- </xsl:template>
-
-<xsl:template name="reducedotpath"><xsl:param name="file"/>
-	<xsl:choose>	
-		<xsl:when test="starts-with($file,'./')">
-			<xsl:call-template name="reducedotpath">
-        		<xsl:with-param name="file" select="substring($file,3)"/>
-			</xsl:call-template>
-		</xsl:when>
-		<xsl:when test="contains($file,'/./')">
-			<xsl:call-template name="reducepath">
-        		<xsl:with-param name="file">
-	                <xsl:value-of select="substring-before($file,'/./')"/>
-			        <xsl:text>/</xsl:text>
-					<xsl:value-of select="substring-after($file,'/./')"/>
-				</xsl:with-param>
-			</xsl:call-template>
-		</xsl:when>
-		<xsl:when test="substring($file,string-length($file) - 1) = '/.'">
-           <xsl:value-of select="substring($file,1,string-length($file) - 2)"/>
-		</xsl:when>
-		<xsl:otherwise><xsl:value-of select="$file"/></xsl:otherwise>
-	</xsl:choose>
- </xsl:template>
+<xsl:include href="path-module.xsl"/>
 
 <!-- overridable templates follow -->
 
--- a/sysmodelgen/core/joinsysdef.xsl	Wed Sep 22 13:41:43 2010 +0100
+++ b/sysmodelgen/core/joinsysdef.xsl	Tue Sep 28 17:48:51 2010 +0100
@@ -14,9 +14,17 @@
 	Create a stand-alone sysdef from a linked set of fragments
 -->
  	<xsl:output method="xml" indent="yes"/>
-<!-- create a stand-alone sysdef from a linked set of fragments -->
+<!--Description:This creates a stand-alone sysdef from a linked set of fragments.
+All API metadata will be removed
+-->
+<!--Input:<sysdef> - (required) The 3.0 formatsystem definition XML file to
+		process. This can be a fragment or stand-alone. 
+		If there are no linked fragments, this will just convert all
+		relative unit paths into absolute paths and embed any linked
+		metadata-->
 
 <xsl:param name="path">/os/deviceplatformrelease/foundation_system/system_model/system_definition.xml</xsl:param>
+<!-- <path> - The full system model path for this file. Use forward slashes.-->
 
 <xsl:template match="/*">
 	<xsl:apply-templates select="." mode="join"/>
--- a/sysmodelgen/core/mergesysdef-module.xsl	Wed Sep 22 13:41:43 2010 +0100
+++ b/sysmodelgen/core/mergesysdef-module.xsl	Tue Sep 28 17:48:51 2010 +0100
@@ -10,7 +10,10 @@
 	Nokia Corporation - initial contribution.
 	Contributors:
 	Description:
-	XSLT module for merging only two sysdef files according to the 3.0.0 rules. Old syntax not supported and must be converetd before calling.
+	XSLT module for merging only two sysdef files according to the 3.0.1 rules. 
+		2.x and older syntax not supported and must be converted before calling.
+
+		Requires the including XSLT to also include path-module.xsl
 -->
 	
 <xsl:variable name="defaultnamespace">http://www.symbian.org/system-definition</xsl:variable>
@@ -42,7 +45,7 @@
 </xsl:template>
 
 
-<xsl:template match="@id|@before" mode="translate-namespaces"><xsl:param name="nsdoc"/>
+<xsl:template match="@id|@before|@replace" mode="translate-namespaces"><xsl:param name="nsdoc"/>
 	<xsl:attribute name="{name()}">
 		<xsl:variable name="id">
 			<xsl:choose>
@@ -135,7 +138,13 @@
 	</xsl:if>
 	 
 	<xsl:copy>
-		<xsl:copy-of  select="@*"/> <!--  use attributes from origin model -->
+		<xsl:attribute name="schema">
+			<xsl:call-template name="compare-versions">
+				<xsl:with-param name="v1" select="@schema"/>
+				<xsl:with-param name="v2" select="$other/@schema"/>
+			</xsl:call-template>
+		</xsl:attribute>
+		<xsl:copy-of  select="@*[name()!='schema']"/> <!--  use attributes from origin model -->
 		<xsl:variable name="namespaces">
 			<xsl:copy> <!-- needs <copy> so the processor doesn't lose the namespaces -->
 				<!--copy namespaces as needed -->
@@ -183,6 +192,7 @@
 			<xsl:with-param name="other" select="exslt:node-set($otherdoc)/*"/>
 			<xsl:with-param name="up" select="$up"/>
 			<xsl:with-param name="down" select="$down"/>
+			<xsl:with-param name="replaces" select="exslt:node-set($otherdoc)//*[self::component or self::collection or self::package or self::layer]/@replace"/>
 		</xsl:apply-templates>
 	
 	</xsl:copy>
@@ -192,6 +202,7 @@
 	<xsl:param name="other"/>	<!-- the parent of the downstream systemModel this is merged with -->
 	<xsl:param name="up"/>
 	<xsl:param name="down"/>
+	<xsl:param name="replaces"/>
 	<xsl:copy><xsl:copy-of  select="@*"/>
 		<!--  copy metas and comments in between meta. Do not try to merge metadata between models -->
 			<xsl:copy-of select="meta | $other/systemModel/meta | comment()[following-sibling::meta]"/>	
@@ -199,7 +210,16 @@
 			<xsl:with-param name="other" select="$other/systemModel"/>
 			<xsl:with-param name="up" select="$up"/>
 			<xsl:with-param name="down" select="$down"/>
+			<xsl:with-param name="replaces" select="$replaces"/>
 		</xsl:apply-templates>
+
+		<!-- tack on any remaining layers -->
+		<xsl:apply-templates mode="merge-copy-of" select="$other/systemModel/layer[not(@before) and not(following-sibling::*[@id=current()/layer/@id]) and not(@id=current()/layer/@id)]">
+			<xsl:with-param name="origin" select="$down"/>
+			<xsl:with-param name="root" select="current()/.."/>
+			<xsl:with-param name="replaces" select="$replaces"/>
+		</xsl:apply-templates>		
+
 	</xsl:copy>
 </xsl:template>
 
@@ -235,7 +255,7 @@
 			<xsl:attribute name="levels"><xsl:value-of select="normalize-space($lev)"/></xsl:attribute>
 		</xsl:when>
 		<xsl:otherwise> <!--  if they differ, use the origin's levels -->
-			<xsl:message>Note: levels differ "<xsl:value-of select="."/>" vs "<xsl:value-of select="$other/@levels"/>"</xsl:message>
+			<xsl:message>Note: levels differ "<xsl:value-of select="."/>" vs "<xsl:value-of select="$other/@levels"/>" on <xsl:value-of select="../@id"/></xsl:message>
 			<xsl:copy-of select="."/>
 		</xsl:otherwise>
 	</xsl:choose>
@@ -252,67 +272,16 @@
 	<xsl:choose>
 		<xsl:when test="not($to-sort)"/>  <!-- nothing left to copy. stop -->
 		<xsl:when test="not($base)"/>  <!-- reached end. stop -->
-		<xsl:when test="$base[1]/@id=$end/following-sibling::*[1]/@id"/> <!-- passed $end. Stop -->
-		<xsl:when test="$base[1]/@id = $to-sort[1]/@id">  <!-- both lists start with same item -->
-			<xsl:if test="$base[1]/@id!=$end/@id"> <!-- not at end, so keep going -->
-				<xsl:call-template name="copy-sorted-content">
-					<xsl:with-param name="base" select="$base[position() != 1]"/>
-					<xsl:with-param name="to-sort" select="$to-sort[position() != 1]"/>
-					<xsl:with-param name="remainder" select="$remainder"/>
-					<xsl:with-param name="start" select="$start"/>
-					<xsl:with-param name="end" select="$end"/>
-					<xsl:with-param name="down" select="$down"/>
-				</xsl:call-template>		
-			</xsl:if>
-		</xsl:when>	
-		<xsl:when test="$remainder[@id = $base[1]/@id]"> <!-- left over item is in $base -->
-			<xsl:call-template name="copy-sorted-content">
-				<xsl:with-param name="base" select="$base[position() != 1]"/>
-				<xsl:with-param name="to-sort" select="$to-sort"/>
-				<xsl:with-param name="remainder" select="$remainder[@id != $base[1]/@id]"/>
-				<xsl:with-param name="start" select="$start"/>
-				<xsl:with-param name="end" select="$end"/>
-				<xsl:with-param name="down" select="$down"/>
-			</xsl:call-template>		
-		</xsl:when>
-		<xsl:when test="not($base[@id = $to-sort[1]/@id])"> <!-- in to-sort, but not base -->		
-			<xsl:if test="$base[1]/@id=$end/@id  and not($base[@id=$to-sort[1]/@before])">
-			 	<!-- if at end, then this needs to be copied
-					don't copy if the before ID is found in $base	-->
-				<xsl:apply-templates mode="merge-copy-of" select="$to-sort[1]">
-					<xsl:with-param name="origin" select="$down"/>
-					<xsl:with-param name="root" select="$end/ancestor::systemModel"/>
-				</xsl:apply-templates>
-			</xsl:if>			
-		<xsl:call-template name="copy-sorted-content">
-			<xsl:with-param name="base" select="$base"/>
-			<xsl:with-param name="to-sort" select="$to-sort[position() != 1]"/>
-			<xsl:with-param name="remainder" select="$remainder"/>
-			<xsl:with-param name="start" select="$start"/>
-			<xsl:with-param name="end" select="$end"/>
-			<xsl:with-param name="down" select="$down"/>
-		</xsl:call-template>		
-		</xsl:when>	
-		<xsl:when test="not($to-sort[@id = $base[1]/@id])"> <!-- in base, but not to-sort -->		
-		<xsl:call-template name="copy-sorted-content">
-			<xsl:with-param name="base" select="$base[position() != 1]"/>
-			<xsl:with-param name="to-sort" select="$to-sort"/>
-			<xsl:with-param name="remainder" select="$remainder"/>
-			<xsl:with-param name="start" select="$start"/>
-			<xsl:with-param name="end" select="$end"/>
-			<xsl:with-param name="down" select="$down"/>
-		</xsl:call-template>		
-		</xsl:when>	
-		<xsl:when test="$base[@id = $to-sort[1]/@id]"> <!-- is in base, but not 1st one-->
-			<xsl:call-template name="copy-sorted-content">
-				<xsl:with-param name="base" select="$base"/>
-				<xsl:with-param name="to-sort" select="$to-sort[position() != 1] "/>
-				<xsl:with-param name="remainder" select="$remainder | $to-sort[1]"/>
-				<xsl:with-param name="start" select="$start"/>
-				<xsl:with-param name="end" select="$end"/>
-				<xsl:with-param name="down" select="$down"/>
-			</xsl:call-template>
-		</xsl:when>	
+		<xsl:otherwise>
+			<xsl:for-each select="$to-sort">
+				<xsl:if test="((@before=$end/@id) or not(@before) or not($base/ancestor::SystemDefinition//*[@id=current()/@before])) and not($base[@id=current()/@id])">
+					<xsl:apply-templates mode="merge-copy-of" select=".">
+						<xsl:with-param name="origin" select="$down"/>
+						<xsl:with-param name="root" select="$end/ancestor::SystemDefinition"/>
+					</xsl:apply-templates>
+				</xsl:if>
+			</xsl:for-each>
+		</xsl:otherwise>	
 	</xsl:choose>
 </xsl:template>
 
@@ -353,47 +322,94 @@
 </xsl:template>
 
 
+<xsl:template name="best-prev"><xsl:param name="cur" select="."/><xsl:param name="alt"/>
+<xsl:if test="$alt">
+<xsl:variable name="prev" select="$cur/preceding-sibling::*[@id][1]"/> 
+<xsl:choose>
+	<xsl:when test="not($prev)"/>
+	<xsl:when test="$alt/preceding-sibling::*[@id=$prev/@id]"><xsl:value-of select="$prev/@id"/></xsl:when>
+	<xsl:otherwise>
+		<xsl:call-template name="best-prev">
+			<xsl:with-param name="cur" select="$prev"/>
+			<xsl:with-param name="alt" select="$alt"/>
+		</xsl:call-template>
+	</xsl:otherwise>
+</xsl:choose>
+</xsl:if>
+</xsl:template>
+
 <xsl:template match="layer | package | collection | component" mode="merge-models">
 	<xsl:param name="other"/>	<!-- the downstream item of the parent's rank that contains a potential items this is merged with -->
 	<xsl:param name="up"/>
 	<xsl:param name="down"/>
+	<xsl:param name="replaces"/>
 	<xsl:variable name="this" select="."/>	<!-- current item -->
-	
 	<!-- match = this item in the downstream model -->	
 	<xsl:variable name="match" select="$other/*[@id=current()/@id]"/>
-	
-	
-	<!-- prev = the previous item before the current one (no metas, only named items)-->
-	<xsl:variable name="prev" select="preceding-sibling::*[@id][1]"/> 
-
-	<!-- copy all items between this and prev  that are solely in the downstream model -->	 		
 
 	<xsl:choose>
-		<xsl:when test="$match and (not($prev) or $other/*[@id= $prev/@id] )">
+		<xsl:when test="$replaces[.=$this/@id] or (self::component and $match)">  <!-- replace the item instead of merge -->
+			<xsl:message>Note: <xsl:value-of select="name()"/> "<xsl:value-of select="@id"/>" in "<xsl:value-of select="../@id"/>" <xsl:choose>
+					<xsl:when test="self::component and $match">overridden in downstream sysdef</xsl:when>
+					<xsl:otherwise><xsl:for-each select="$replaces[.=$this/@id]/..">replaced by <xsl:value-of select="name()"/> "<xsl:value-of select="@id"/>" in "<xsl:value-of select="../@id"/>"</xsl:for-each></xsl:otherwise>
+				</xsl:choose>
+			</xsl:message>
+			<!-- if the removed item is in the downstream doc, just copy that and ignore the upstream contents -->
+			<xsl:apply-templates mode="merge-copy-of" select="$match">
+				<xsl:with-param name="origin" select="$down"/>
+				<xsl:with-param name="root" select="$this/ancestor::SystemDefinition"/>			
+				<xsl:with-param name="replaces" select="$replaces"/>
+			</xsl:apply-templates>		
+		</xsl:when>
+		<xsl:otherwise>
+			<!-- remove this if it's in the list of stuff to be replaced-->
+
+<xsl:variable name="prev-id">
+	<xsl:call-template name="best-prev">
+		<xsl:with-param name="alt" select="$match"/>
+	</xsl:call-template>
+</xsl:variable>
+
+	<!-- prev = the previous item before the current one (no metas, only named items)-->
+	<xsl:variable name="prev" select="preceding-sibling::*[@id=$prev-id]"/> 
+
+
+	<!-- copy all items between this and prev that are solely in the downstream model -->	 		
+
+	<!-- <xsl:variable name="upstream-ids" select="ancestor::SystemDefinition//@id[parent::component or parent::collection or parent::package or parent::layer]"/> -->
+	<xsl:variable name="upstream-ids" select="../*/@id"/> <!-- this is much faster than using all IDs. before only currently works in the same parent anyway -->
+
+	<!-- $upstream-ids is used to avoid inserting an item that's being moved -->
+
+	<xsl:choose>
+		<xsl:when test="$match and $prev">
 			<xsl:call-template name="copy-sorted-content">
 				<xsl:with-param name="base" select="../*[@id]"/>
-				<xsl:with-param name="to-sort" select="$other/*[@id]"/>
+				<xsl:with-param name="to-sort" select="$other/*[@id and not(@before=$upstream-ids)][following-sibling::*[@id=$match/@id]][preceding-sibling::*[@id=$prev/@id]]"/>
 				<xsl:with-param name="start" select="$prev"/>
 				<xsl:with-param name="end" select="."/>
 				<xsl:with-param name="down" select="$down"/>
 			</xsl:call-template>
 		</xsl:when>
-	<xsl:when test="not($match/preceding-sibling::*[@id=$this/../*/@id]) and $other/*[@id= current()/@id]/preceding-sibling::*[@id and not(@before)]">
-		<!-- if this is the first item in other that's also in this, then put all new items from other here -->
-		<xsl:apply-templates mode="merge-copy-of" select="$match/preceding-sibling::*[@id and not(@before)]">
-			<xsl:with-param name="origin" select="$down"/>
-			<xsl:with-param name="root" select="$this/ancestor::systemModel"/>	
-		</xsl:apply-templates>
-	</xsl:when>
+		<xsl:when test="$match and not($prev)">
+			<xsl:call-template name="copy-sorted-content">
+				<xsl:with-param name="base" select="../*[@id]"/>
+				<xsl:with-param name="to-sort" select="$other/*[@id and not(@before=$upstream-ids)][following-sibling::*[@id=$match/@id]]"/>
+				<xsl:with-param name="start" select="$prev"/>
+				<xsl:with-param name="end" select="."/>
+				<xsl:with-param name="down" select="$down"/>
+			</xsl:call-template>
+		</xsl:when>
 	</xsl:choose>
 
  	<!-- just copy anything identified as being before this, assume they're all ok -->
+
 	<xsl:apply-templates mode="merge-copy-of" select="$other/*[@before=current()/@id]">
 		<xsl:with-param name="remove-before" select="1"/>
 		<xsl:with-param name="origin" select="$down"/>
-		<xsl:with-param name="root" select="$this/ancestor::systemModel"/>	
+		<xsl:with-param name="root" select="$this/ancestor::SystemDefinition"/>	
+		<xsl:with-param name="replaces" select="$replaces"/>
 	</xsl:apply-templates>
-
 	
 	<xsl:copy>
 		<xsl:apply-templates select="@*" mode="merge-models"> <!-- copy upstream attributes -->
@@ -410,9 +426,16 @@
 			</xsl:if>
 		</xsl:if>
 		
-		<xsl:for-each select="$match/@*">  <!-- copy downstream attributes, only if not set on upstream -->
+		<xsl:for-each select="$match/@*[name()!='replace']">  <!-- copy downstream attributes, only if not set on upstream -->
 			<xsl:if test="not($this/@*[name()=name(current())])"><xsl:copy-of select="."/></xsl:if>
 		</xsl:for-each>
+
+		<xsl:if test="$match/@replace"> <!-- check replace separately -->
+			<xsl:if test="not($this/ancestor::SystemDefinition//*[(self::component or self::collection or self::package or self::layer) and $match/@replace=@id])">
+				<!-- only remove replace if it's been used -->
+				<xsl:copy-of select="$match/@replace"/>
+			</xsl:if>
+		</xsl:if>
 		
 		<xsl:choose>
 			<xsl:when test="self::component">
@@ -435,27 +458,24 @@
 					<xsl:with-param name="other" select="$match"/>
 					<xsl:with-param name="up" select="$up"/>
 					<xsl:with-param name="down" select="$down"/>
+					<xsl:with-param name="replaces" select="$replaces"/>
 				</xsl:apply-templates>
 				<!--  don't copy if explicitly or implicitly placed already-->
 				<xsl:for-each select="$match/*[not(@before) and not(following-sibling::*[@id=$this/*/@id])]">
 					<xsl:if test="not($this/*[@id=current()/@id])">
 						<xsl:apply-templates mode="merge-copy-of" select=".">
 							<xsl:with-param name="origin" select="$down"/>
-							<xsl:with-param name="root" select="$this/ancestor::systemModel"/>			
+							<xsl:with-param name="root" select="$this/ancestor::SystemDefinition"/>			
+							<xsl:with-param name="replaces" select="$replaces"/>
 						</xsl:apply-templates>
 					</xsl:if>
 				</xsl:for-each>
 			</xsl:otherwise>
 		</xsl:choose>
 	</xsl:copy>
-	
-	<xsl:if test="self::layer and not(following-sibling::layer)">	
-		<!-- for the last layer, tack on any remaining layers -->
-		<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)]">
-			<xsl:with-param name="origin" select="$down"/>
-			<xsl:with-param name="root" select="$this/ancestor::systemModel"/>			
-		</xsl:apply-templates>		
-	</xsl:if>
+
+		</xsl:otherwise>
+	</xsl:choose>
 </xsl:template>
 
 
@@ -464,10 +484,11 @@
 	<xsl:param name="remove-before" select="0"/> <!-- set to true if any before attribute is to be removed -->
 	<xsl:param name="origin"/>	<!--the element containing the @name to use the origin-model attribute  -->
 	<xsl:param name="root"/> 	<!--the systemModel element in the upstream doc  -->
-
+	<xsl:param name="replaces" select="ancestor::SystemDefinition/descendant::*[(self::component or self::collection or self::package or self::layer) and not(ancestor::meta)]/@replace"/> <!-- recalculate this is necessarfy, but should just pass down as a param -->
+	<xsl:variable name="moved" select="$root/descendant::*[name()=name(current()/..) and @id!=current()/../@id]/*[@id=current()/@id]"/>
 	<xsl:choose>
 		<!-- this might slow things down, consider making optional -->
-		<xsl:when test="not(self::layer) and count($root/descendant::*[name()=name(current()/..) and @id!=current()/../@id]/*[@id=current()/@id])">
+		<xsl:when test="not(self::layer) and (count($moved) and not($moved[ancestor-or-self::*/@id=$replaces]) )">
 			<xsl:message>Warning: <xsl:value-of select="name()"/> "<xsl:value-of select="@id"/>" moved in downstream model. Ignoring moved <xsl:value-of select="name()"/>
 				<xsl:text>&#xa;</xsl:text>
 			</xsl:message>
@@ -478,6 +499,7 @@
 				<xsl:apply-templates select="*|comment()" mode="merge-copy-of">
 					<xsl:with-param name="origin" select="$origin"/>
 					<xsl:with-param name="root" select="$root"/>
+					<xsl:with-param name="replaces" select="$replaces"/>
 				</xsl:apply-templates>
 			</xsl:variable>
 			<xsl:choose>
@@ -489,12 +511,10 @@
 				</xsl:when>
 				<xsl:otherwise>
 					<xsl:copy>
-						<xsl:choose>
-							<xsl:when test="$remove-before">
-								<xsl:copy-of select="@*[name()!='before']"/>
-							</xsl:when>
-							<xsl:otherwise><xsl:copy-of select="@*"/></xsl:otherwise>
-						</xsl:choose>
+						<xsl:call-template name="merge-copy-of-atts">
+							<xsl:with-param name="remove-before" select="$remove-before"/>
+							<xsl:with-param name="root" select="$root"/>
+						</xsl:call-template>
 						<xsl:copy-of select="exslt:node-set($content)"/>
 					</xsl:copy>
 				</xsl:otherwise>
@@ -502,17 +522,31 @@
 		</xsl:otherwise>
 	</xsl:choose>
 </xsl:template>
+<xsl:template match="comment()|@*" mode="merge-copy-of">
+	<xsl:copy-of select="."/>
+</xsl:template>
 
 
-<xsl:template match="comment()|@*" mode="merge-copy-of">
-	<xsl:copy-of select="."/>
+<xsl:template name="merge-copy-of-atts">
+	<xsl:param name="remove-before" select="0"/> <!-- set to true if any before attribute is to be removed -->
+	<xsl:param name="root"/> 	<!--the systemModel element in the upstream doc  -->
+	
+	<xsl:choose>
+		<xsl:when test="$remove-before">
+			<xsl:copy-of select="@*[name()!='before' and name()!='replace']"/>
+		</xsl:when>
+		<xsl:otherwise><xsl:copy-of select="@*[name()!='replace']"/></xsl:otherwise>
+	</xsl:choose>
+	<xsl:if test="@replace and not($root/descendant::*[(self::component or self::collection or self::package or self::layer) and @id=current()/@replace])">
+		<!-- only include replace if it's not been used -->
+		<xsl:copy-of select="@replace"/>
+	</xsl:if>
 </xsl:template>
 
 <xsl:template match="component" mode="merge-copy-of">
 	<xsl:param name="remove-before" select="0"/> <!-- set to true if any before attribute is to be removed -->
 	<xsl:param name="origin"/>	<!--the element containing the @name to use the origin-model attribute  -->
 	<xsl:param name="root"/> 	<!--the systemModel element in the upstream doc  -->
-	
 	<xsl:choose>
 		<!-- this might slow things down, consider making optional -->
 		<xsl:when test="$root/descendant::collection[@id!=current()/../@id]/component[@id=current()/@id]">
@@ -522,12 +556,10 @@
 		</xsl:when>
 		<xsl:otherwise>
 			<xsl:copy>
-				<xsl:choose>
-					<xsl:when test="$remove-before">
-						<xsl:copy-of select="@*[name()!='before']"/>
-					</xsl:when>
-					<xsl:otherwise><xsl:copy-of select="@*"/></xsl:otherwise>
-				</xsl:choose>
+				<xsl:call-template name="merge-copy-of-atts">
+					<xsl:with-param name="remove-before" select="$remove-before"/>
+					<xsl:with-param name="root" select="$root"/>
+				</xsl:call-template>
 				<xsl:if test="not(@origin-model) and $origin/@name">
 					<xsl:attribute name="origin-model">
 						<xsl:value-of select="$origin/@name"/>
@@ -536,10 +568,63 @@
 						<xsl:copy-of select="$origin/@root"/>
 					</xsl:if>
 				</xsl:if>
-				<xsl:copy-of select="*|comment()"/>
+				<xsl:apply-templates select="*|comment()" mode="merge-copy-of">
+					<xsl:with-param name="origin" select="$origin"/>
+					<xsl:with-param name="root" select="$root"/>
+				</xsl:apply-templates>
 			</xsl:copy>
 		</xsl:otherwise>
 	</xsl:choose>
 </xsl:template>
 
+
+<xsl:template match="unit" mode="merge-copy-of">
+	<xsl:param name="origin"/>	<!--the element containing the @name to use the origin-model attribute  -->
+	<xsl:param name="root"/> 	<!--the systemModel element in the upstream doc  -->
+	<xsl:copy>
+				<xsl:apply-templates select="@*" mode="merge-copy-of">
+					<xsl:with-param name="origin" select="$origin"/>
+					<xsl:with-param name="root" select="$root"/>
+				</xsl:apply-templates>
+	</xsl:copy>
+</xsl:template>
+
+
+
+
+<xsl:template match="meta" mode="merge-copy-of">
+	<xsl:param name="origin"/>	<!--the element containing the @name to use the origin-model attribute  -->
+	<xsl:param name="root"/> 	<!--the systemModel element in the upstream doc  -->
+	<xsl:copy>
+		<xsl:apply-templates select="@*" mode="merge-copy-of">
+			<xsl:with-param name="origin" select="$origin"/>
+			<xsl:with-param name="root" select="$root"/>
+		</xsl:apply-templates>
+		<xsl:copy-of select="node()"/>
+	</xsl:copy>
+</xsl:template>
+
+
+<xsl:template match="unit/@bldFile | unit/@mrp | unit/@base | meta/@href" mode="merge-copy-of">
+	<xsl:param name="origin" select="/.."/>	<!--the element containing the @name to use the origin-model attribute  -->
+
+	<xsl:attribute name="{name()}">
+		<xsl:choose>
+			<xsl:when test="not($origin/@pathto)"><xsl:value-of select="."/></xsl:when>
+			<xsl:when test="(contains(.,'://') and not(contains(substring-before(.,'://'),'/'))) or starts-with(.,'/')"> <!-- absolute URI or absolute path-->
+				<xsl:value-of select="."/>
+			</xsl:when>
+			<xsl:when test="contains($origin/@pathto,'://') and not(contains(substring-before($origin/@pathto,'://'),'/'))"> <!-- absolute URI for downstream sysdef not valif for unit paths, just copy and raise warning-->
+				<xsl:message>ERROR: Could not resolve relative path in downstream file: <xsl:value-of select="."/> relative to absolute URI <xsl:value-of select="$origin/@pathto"/></xsl:message>
+				<xsl:value-of select="."/>
+			</xsl:when>
+		<xsl:otherwise> <!-- relative link -->
+			<xsl:call-template name="joinpath">
+				<xsl:with-param name="file" select="$origin/@pathto"/>
+				<xsl:with-param name="rel" select="."/>
+			</xsl:call-template>
+		</xsl:otherwise>
+		</xsl:choose>
+	</xsl:attribute>
+</xsl:template>
 </xsl:stylesheet>
--- a/sysmodelgen/core/mergesysdef.xsl	Wed Sep 22 13:41:43 2010 +0100
+++ b/sysmodelgen/core/mergesysdef.xsl	Tue Sep 28 17:48:51 2010 +0100
@@ -1,4 +1,4 @@
-<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:exslt="http://exslt.org/common">
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:exslt="http://exslt.org/common" exclude-result-prefixes="exslt">
 <!--Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
 	All rights reserved.
 	This component and the accompanying materials are made available
@@ -13,12 +13,20 @@
 	Merge two 3.x syntax system definitions
 -->
 
+<!--Description:This merges two 3.x syntax system definitions.
+It can process two standalone sysdefs or two sysdef fragments which describe
+the same system model item.
+If the sysdefs are not the same schema, the output will use the highest schema
+value of the two.
+-->
+<!--Input:<sysdef> - (required) The system definition XML file to process in the 3.0 format, and can be a fragment or stand-alone.
+	If a fragment, this must be the same rank as the Downstream sysdef-->
+<!--Output:<sysdef> - (optional) The system definition XML file to save the output as. If not present it will write to stdout.-->
+
 	<xsl:output method="xml" indent="yes"/>
-	<xsl:param name="Downstream">mcl/System_Definition_Template.xml</xsl:param>
+	<xsl:param name="Downstream">mcl/System_Definition_Template.xml</xsl:param> <!-- <sysdef> - (required) The path to the downstream systef relative to the upstream one (ie the -in sysdef). -->
 	<xsl:key name="origin" match="component" use="@origin-model"/>
 
-<!-- only supports 3.x syntax and only operates on stand-alone models -->
-
 <xsl:variable name="downstream" select="document($Downstream,.)/SystemDefinition"/>
 <xsl:param name="upname">
 	<xsl:choose>
@@ -39,6 +47,7 @@
 		<xsl:otherwise><xsl:value-of select="/SystemDefinition/systemModel/@name"/></xsl:otherwise>
 	</xsl:choose>
 </xsl:param>
+<!-- [name] - (optional) The name used in the origin-model attribute of any component that comes from the upstream sysdef. Defaults to the name attribute on the systemModel element, or "Upstream"-->
 
 <xsl:param name="downname">
 	<xsl:choose>
@@ -53,6 +62,7 @@
 		<xsl:otherwise><xsl:value-of select="$downstream/systemModel/@name"/></xsl:otherwise>
 	</xsl:choose>
 </xsl:param>
+<!-- [name] - (optional) The name used in the origin-model attribute of any component that comes from the downstream sysdef. Defaults to the name attribute on the systemModel element, or "Downstream"-->
 
 <xsl:template mode="origin-term" match="*">
 	<xsl:param name="root"/>
@@ -77,7 +87,21 @@
 </xsl:template>
 
 
-<!--  this merge only two files according to the 3.0.0 rules. Old syntax not supported. Must be converetd before calling -->
+<!-- choose the greater of the two versions -->
+<xsl:template name="compare-versions"><xsl:param name="v1"/><xsl:param name="v2"/>
+			<xsl:choose>
+				<xsl:when test="$v1=$v2"><xsl:value-of select="$v1"/></xsl:when>
+				<xsl:when test="substring-before($v1,'.') &gt; substring-before($v2,'.')"><xsl:value-of select="$v1"/></xsl:when>
+				<xsl:when test="substring-before($v1,'.') &lt; substring-before($v2,'.')"><xsl:value-of select="$v2"/></xsl:when>
+				<xsl:when test="substring-before(substring-after($v1,'.'),'.') &gt; substring-before(substring-after($v2,'.'),'.')"><xsl:value-of select="$v1"/></xsl:when>
+				<xsl:when test="substring-before(substring-after($v1,'.'),'.') &lt; substring-before(substring-after($v2,'.'),'.')"><xsl:value-of select="$v2"/></xsl:when>
+				<xsl:when test="substring-after(substring-after($v1,'.'),'.') &gt; substring-after(substring-after($v2,'.'),'.')"><xsl:value-of select="$v1"/></xsl:when>
+				<xsl:when test="substring-after(substring-after($v1,'.'),'.') &lt; substring-after(substring-after($v2,'.'),'.')"><xsl:value-of select="$v2"/></xsl:when>
+				<xsl:otherwise><xsl:value-of select="$v1"/></xsl:otherwise>
+			</xsl:choose>
+</xsl:template>
+
+<!--  this merge only two files according to the 3.0.x rules. Old syntax not supported. Must be converetd before calling -->
 
 
 
@@ -86,7 +110,7 @@
 		<sysdef name="{$upname}"/>
 	</xsl:variable>
 	<xsl:variable name="downmodel">
-		<sysdef name="{$downname}"/>
+		<sysdef name="{$downname}" pathto="{$Downstream}"/>
 	</xsl:variable>
 	
 	<xsl:choose>
@@ -105,5 +129,13 @@
 	</xsl:choose>
 </xsl:template>
 
+<xsl:include href="path-module.xsl"/>
 <xsl:include href="mergesysdef-module.xsl"/>
+<xsl:template match="@*[local-name()='proFile' or local-name()='qmakeArgs'  or namespace-uri()='qt']" mode="merge-copy-of">
+	<!-- this fixes a xalan-j bug where it changes the namespace in the merged model to just "qt"-->
+	<xsl:attribute name="{local-name()}" namespace="http://www.nokia.com/qt">
+		<xsl:value-of select="."/>
+	</xsl:attribute>
+</xsl:template>
+
 </xsl:stylesheet>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysmodelgen/core/path-module.xsl	Tue Sep 28 17:48:51 2010 +0100
@@ -0,0 +1,110 @@
+<?xml version="1.0"?>
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+<!--Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+	All rights reserved.
+	This component and the accompanying materials are made available
+	under the terms of the License "Eclipse Public License v1.0"
+	which accompanies this distribution, and is available
+	at the URL "http://www.eclipse.org/legal/epl-v10.html".
+
+	Initial Contributors:
+	Nokia Corporation - initial contribution.
+	Contributors:
+	Description:
+	XSLT module which contains named templates which process file paths
+-->
+
+ <xsl:template name="lastbefore"><xsl:param name="string"/><xsl:param name="substr" select="'/'"/>
+        <xsl:if test="contains($string,$substr)">
+                <xsl:value-of select="substring-before($string,$substr)"/>
+                <xsl:if test="contains(substring-after($string,$substr),$substr)">
+	                <xsl:value-of select="$substr"/>
+	              </xsl:if>
+        <xsl:call-template name="lastbefore">
+                <xsl:with-param name="string" select="substring-after($string,$substr)"/>
+                <xsl:with-param name="substr" select="$substr"/>
+        </xsl:call-template>
+        </xsl:if>
+</xsl:template>
+
+ <xsl:template name="joinpath"><xsl:param name="file"/><xsl:param name="rel"/>
+	<xsl:choose>
+		<xsl:when test="(contains($rel,'://') and not(contains(substring-before($rel,'://'),'/'))) or starts-with($rel,'/')"> <!-- absolute URI or absolute path-->
+			<xsl:value-of select="$rel"/>
+		</xsl:when>
+		<xsl:otherwise> <!-- relative link -->
+			<xsl:call-template name="reducepath">
+				<xsl:with-param name="file">
+					<xsl:call-template name="lastbefore">
+						<xsl:with-param name="string" select="$file"/>
+					</xsl:call-template>
+					<xsl:text>/</xsl:text>
+					<xsl:value-of select="$rel"/>
+				</xsl:with-param>
+			</xsl:call-template>
+		</xsl:otherwise>
+	</xsl:choose>
+ </xsl:template>
+
+<xsl:template name="reducepath"><xsl:param name="file"/>
+	<xsl:call-template name="reducedotdotpath">
+    	<xsl:with-param name="file">
+			<xsl:call-template name="reducedotpath">
+		    	<xsl:with-param name="file" select="$file"/>
+		    </xsl:call-template>
+		</xsl:with-param>
+	</xsl:call-template>
+</xsl:template>
+
+<xsl:template name="reducedotdotpath"><xsl:param name="file"/>
+	<xsl:variable name="pre">
+		<xsl:call-template name="lastbefore">
+			    <xsl:with-param name="string" select="substring-before($file,'/../')"/>
+		</xsl:call-template>
+	</xsl:variable>
+	<xsl:choose>
+		<xsl:when test="starts-with($file,'../')">
+			<xsl:text>../</xsl:text>
+			<xsl:call-template name="reducedotdotpath">
+        		<xsl:with-param name="file" select="substring($file,4)"/>
+			</xsl:call-template>
+		</xsl:when>
+		<xsl:when test="contains($file,'/../') and $pre='' and not(starts-with($file,'/'))"> <!-- if file is a relative path and the dotdots go up to the top dir, don't start with a slash -->
+			<xsl:call-template name="reducepath">
+        		<xsl:with-param name="file" select="substring-after($file,'/../')"/>
+			</xsl:call-template>
+		</xsl:when>
+		<xsl:when test="contains($file,'/../')">
+			<xsl:call-template name="reducepath">
+        		<xsl:with-param name="file" select="concat($pre,'/',substring-after($file,'/../'))"/>
+			</xsl:call-template>
+		</xsl:when>
+		<xsl:otherwise><xsl:value-of select="$file"/></xsl:otherwise>
+	</xsl:choose>
+ </xsl:template>
+
+<xsl:template name="reducedotpath"><xsl:param name="file"/>
+	<xsl:choose>	
+		<xsl:when test="starts-with($file,'./')">
+			<xsl:call-template name="reducedotpath">
+        		<xsl:with-param name="file" select="substring($file,3)"/>
+			</xsl:call-template>
+		</xsl:when>
+
+		<xsl:when test="contains($file,'/./')">
+			<xsl:call-template name="reducepath">
+        		<xsl:with-param name="file">
+	                <xsl:value-of select="substring-before($file,'/./')"/>
+			        <xsl:text>/</xsl:text>
+					<xsl:value-of select="substring-after($file,'/./')"/>
+				</xsl:with-param>
+			</xsl:call-template>
+		</xsl:when>
+		<xsl:when test="substring($file,string-length($file) - 1) = '/.'">
+           <xsl:value-of select="substring($file,1,string-length($file) - 2)"/>
+		</xsl:when>
+		<xsl:otherwise><xsl:value-of select="$file"/></xsl:otherwise>
+	</xsl:choose>
+ </xsl:template>
+
+</xsl:stylesheet>
--- a/sysmodelgen/extra/dependencies.xsl	Wed Sep 22 13:41:43 2010 +0100
+++ b/sysmodelgen/extra/dependencies.xsl	Tue Sep 28 17:48:51 2010 +0100
@@ -175,7 +175,7 @@
 				</xsl:for-each>
 				<xsl:call-template name="lower-rank">
 					<xsl:with-param name="e1" select="$e"/>
-					<xsl:with-param name="e2" select="name($used[../../@id=current()/@id])"/>
+					<xsl:with-param name="e2" select="name($used[../../@id=current()/@id]/../..)"/>
 				</xsl:call-template>
 			</xsl:with-param>
 			<xsl:with-param name="h0" select="$h"/>
--- a/sysmodelgen/rsc/ModelTemplate.xml	Wed Sep 22 13:41:43 2010 +0100
+++ b/sysmodelgen/rsc/ModelTemplate.xml	Tue Sep 28 17:48:51 2010 +0100
@@ -1,5 +1,5 @@
 <?xml version="1.0"?>
-<model name="Symbian OS" label="System Model" shapes="shapes.xml">
+<model name="Symbian" label="System Model" shapes="shapes.xml">
 	<layout>
 		<legend label="Key">
 			<legend use="@shapes#colors"/>
--- a/sysmodelgen/src/SysModelGen.pm	Wed Sep 22 13:41:43 2010 +0100
+++ b/sysmodelgen/src/SysModelGen.pm	Tue Sep 28 17:48:51 2010 +0100
@@ -82,14 +82,14 @@
 	'iModel'				=> { 'param' => "model=s" ,'type'=>'file/uri', 'default' => "$dataroot/ModelTemplate.xml",
 		'class' => 'Files or URIs', 'desc' => 'The location of the Model XML file to use to build the file. Content of this file will be overridden by anything set on the command line on in an ini file'},
 	'iSysDefFile'				=> { 'param' => "sysdef=s",  'multi' => 1,'type'=>'file/uri', 'xpath' => '/model/sysdef',
-		 'class' => 'Model Control', 'desc' =>  'Comma-separated list of locations for the System Definition XML file(s) used to build the model. Layers in the files will be  stacked on top of each other in order, from bottom to top.'},
+		 'class' => 'Model Control', 'desc' =>  'The System Definition XML file(s) used to build the model.'},
 	"iSourceRoot"			=> {'param'=>'srcvar=s' ,'multi' => 1,
 		 'class' =>  'Model Control'},
-	'iPathPrefix'				=> {'param' => 'sysdef-prefix',   'multi' => 1, 'class' =>  'Model Control'},
+	'iPathPrefix'				=> {'param' => 'sysdef-prefix=s',   'multi' => 1, 'class' =>  'Model Control','type'=>'file/uri',},
 	"iSysDefPath"			=> {'param' => "sysdef-path=s",  'multi' => 1,'type'=>'path',
 		 'class' => 'Model Control', 'desc' =>  'The directory which the system definition file should be considered to be in when turning unit\'s relative links into absolute paths. This is only necessary to provide if the result requires the absolute paths to be meaningful. The order of this parameter must match the order of the -sysdef parameter'},
 	'iShapes'				=> { 'param' => "shapes=s", 'xpath' => '/model/@shapes','type'=>'file/uri',
-		 'class' => 'Files or URIs', 'desc' => 'The location of the Shapes XML file used to provide rules to control  the display of the components on the model. If not present, default behaviour  (in Shapes.xml) is used. This and the default bahaviours are overrriden by  using the -color, -border, -pattern, and -style options. '},
+		 'class' => 'Files or URIs', 'desc' => 'The location of the Shapes XML file used to provide rules to control  the display of the system model items. If not present, default behaviour  (in Shapes.xml) is used. This and the default bahaviours are overrriden by  using the -color, -border, -pattern, and -style options. '},
 	'iLink'				=> { 'param' => "link=s",  'xpath' => '/model/@link',
 		 'class' => 'Files or URIs', 'desc' => 'The base URL to use for all hyperlinks in the model. A base URL will be appended by the type and name (e.g. Blocks/Comms%20Services.html) of the items to create the full URL of the linked file. Window directories will be converted into file URIs.'},
 	'iLinkExpr'				=> { 'param' => "link-expr=s",   'multi' => 1, 'xpath' => 'model/link',
@@ -107,7 +107,7 @@
 	'iCopyright'			=> { 'param' => "copyright=s", 'default' => (1900+$yr[5])." Nokia Corporation",  'xpath' => '/model/@copyright',
 		 'class' =>"Labels", 'desc' =>'The copyright to appear in the lower left. Set to empty string to leave out.'},
 	'iDistribution'		=> { 'param' => "distribution=s",   'xpath' => '/model/@distribution',
-		 'class' => "Labels", 'desc' =>'Text to appear on the bottom centre to indicate to whom the  model can be show. Informational only. Suggested values are "internal", "secret" or "unrestrictred". Not shown if not set.'},
+		 'class' => "Labels", 'desc' =>'Text to appear on the bottom centre to indicate to whom the  model can be shown. Informational only. Suggested values are "internal", "secret" or "unrestrictred". Not shown if not set.'},
 	'iLgdTitle'		=> { 'param' => "legend_title=s",  'xpath' => '/model/layout/legend/@label',
 		'class' =>"Labels", 'desc' =>'The title to appear in the leftmost part of the legend.'},
 	'iLgdFloat'		=> { 'param' => "legend_float=s",  'xpath' => '/model/layout/legend/@float', 'type' => 'boolean',
@@ -127,6 +127,8 @@
 	'iLevels'				=> {  'multi' => 1, 'param' => "levels=s",'type'=>'file/uri' , info=>'levels', 'xpath' => '/model/sysdef',
 		'depr' => "Only works on 2.0 syntax and older models. Use info file instead",
 		'class' =>'Files or URIs', 'desc' => 'The location of the Levels XML file used to override the  stacking of collections. '},
+	'iDepsFile'				=> { 'multi' => 1, 'param' => "deps=s",  'xpath' => '/model/sysdef','type'=>'file/uri',  info=>'extra', 
+		'class' => 'Files or URIs', 'desc' =>  'The location of a sysinfo file containing Dependencies.  If not present, dependencies will not be drawn'},
 
 	'iColor'				=> {  'multi' => 1, 'param' => "color=s", 'xpath' => '/model/layout','type'=>'file/uri', 'info'=>'color',
 		 'class' =>'Files or URIs', 'desc' =>  'The location of a Values XML file used to specify per-component colours. If not present, the default colours are used.'},
@@ -166,8 +168,6 @@
 		 'class' =>'Model Control', 'desc' => 'The width of the drawn image (with units). If not specified it will fit the viewer window. Valid units: "in", "mm", "cm", "px", "pt"'},
 	'iStatic'				=> { 'param' => "static=s", 'type' => 'boolean', 'xpath' => '/model/layout/@static',
 		'class' =>'Model Control', 'desc' => 'If present, the model will not have any mouseover effects (this is  overriden by builing the depmodel).'},
-	'iDepsFile'				=> { 'param' => "deps=s",  'xpath' => '/model/@deps','type'=>'file/uri',
-		'class' => 'Files or URIs', 'desc' =>  'The location of the Dependencies XML file used to draw the depmodel.  If not present, dependencies will not be drawn'},
 	'iPrintResolution'				=>{ 'param' => "dpi=s", 'type' =>  'number', 'xpath' => '/model/layout/@resolution',
 		'class' =>'Model Control', 'desc' => 'The DPI to use when printing from the Adobe SVG Viewer. If not present, it will print well at A4 size. A value of 300 will look good on A3 size paper'},
 	'iModelFont'				=>{'param' => "model_font=s", 'type' =>'font', 'xpath' => '/model/layout/@font',
@@ -242,6 +242,14 @@
 				}
 			}
 		}
+
+	foreach (@ARGV) {
+		# some MS products replace "-" with en-dash in an effort to be "intelligent". 
+		# This replaces all leading en-dashes in the command line with "-" 
+		# There is a small risk that the en-dash is intentional and this will clobber it. 
+		s/^\x96/-/; 
+	}
+
 	GetOptions(%opt);
 
 	if ($self->{'iHelp'})
@@ -598,7 +606,7 @@
 print XSLT '<stylesheet version="1.0" xmlns="http://www.w3.org/1999/XSL/Transform">
 <variable name="fullpath">',$basedir,'/</variable>
 <template match="@*" priority="-2"><copy-of select="."/></template>
-<template match="@href|model/@shapes|model/@deps|logo/@src|legend/@use[not(starts-with(.,&apos;@&apos;) or starts-with(.,&apos;#&apos;))]" priority="-1">
+<template match="@href|model/@shapes|logo/@src|legend/@use[not(starts-with(.,&apos;@&apos;) or starts-with(.,&apos;#&apos;))]" priority="-1">
 	<choose>
 		<when test="$fullpath!=&apos;&apos; and not(contains(.,&apos;:&apos;) or starts-with(.,&apos;/&apos;))">
 			<attribute name="{name()}"><value-of select="concat($fullpath,.)"/></attribute>
@@ -673,7 +681,7 @@
 				} elsif($param eq 'iIgnore' or $param eq 'iIgnoreMeta' or $param eq 'iLinkExpr' or $param eq 'iSysDefFile') {
 					print XSLT "<template match='",$cur->{'xpath'},"'/>\n"	# ignore any already present if set
 				}		
-			} elsif($param eq 'iModel') {
+			} elsif($param eq 'iModel' || $param eq 'iSysDefPath' || $param eq 'iPathPrefix' || $param eq 'iSourceRoot') {
 			} else {
 				print STDERR "$param   ",$self->{$param},"\n";  # should not get here
 			}
@@ -699,7 +707,7 @@
 		$src=$count;
 		if(scalar(@{$self->{'iPathPrefix'}}) == 1) {$src=0}
 		if($self->{'iPathPrefix'}->[$src]) {
-			print XSLT "\t\t<attribute name='prefix'>",$self->{'iPathPrefix'}->[$src],"</attribute>\n";
+			print XSLT "\t\t<attribute name='path-prefix'>",$self->{'iPathPrefix'}->[$src],"</attribute>\n";
 		}
 		$src=$count;
 		if(scalar(@{$self->{'iSysDefPath'}}) == 1) {$src=0}
@@ -835,17 +843,19 @@
 		{
 		return 1;
 		}
+	my $should = 0;
 	my $model = $self->getModel();
 	my $t = $/;
 	$/='>';
 	open(M,$model);
 	while(<M>)
 		{
-		if(/<model\s/){last}
+		if(/<model\s.*deps=/){$should=1;last;}
+		if(/<info\s.*data-type="Dependencies"/){$should=1;last;}
 		}
 	close M;
 	$/ = $t;
-	return /\sdeps=/;
+	return $should
 	}
 
 
@@ -1347,7 +1357,7 @@
   my $head=2;
 while(@list) {
 	$param = shift(@list);
-	if($head<=0 and !($param=~/^-/)){print "\n$param\n";next;}
+	if($head<=0 and !($param=~/^-/)){print STDERR "\n$param\n";next;}
 	$text = shift(@list);
 	write STDERR ;
 	$head--;