Extra warnings, help and bug fixes in sysdeftools perl scripts. Support for 3.0.1 sysdef syntax (replacing when merging) HighFidelityModel
authorBob Rosenberg <bob.rosenberg@nokia.com>
Thu, 06 May 2010 16:31:38 +0100
branchHighFidelityModel
changeset 201 280dc2a9385b
parent 200 6337e330f518
child 202 19ce6071ceaa
Extra warnings, help and bug fixes in sysdeftools perl scripts. Support for 3.0.1 sysdef syntax (replacing when merging)
sysdeftools/joinsysdef-module.xsl
sysdeftools/joinsysdef.pl
sysdeftools/mergesysdef-module.xsl
sysdeftools/mergesysdef.xsl
sysdeftools/rootsysdef.pl
--- a/sysdeftools/joinsysdef-module.xsl	Thu May 06 16:24:41 2010 +0100
+++ b/sysdeftools/joinsysdef-module.xsl	Thu May 06 16:31:38 2010 +0100
@@ -23,8 +23,9 @@
 	<xsl:message terminate="yes">ERROR: Cannot process this document</xsl:message>
 </xsl:template>
 
+<!-- anything in schemas 3.0.x won't add new functional attributes that need processing here, just blindly copy them-->
 
-<xsl:template match="/SystemDefinition[@schema='3.0.0' and count(*)=1]" mode="join">
+<xsl:template match="/SystemDefinition[starts-with(@schema,'3.0.') and count(*)=1]" mode="join">
 	<xsl:param name="origin" select="/.."/>
 	<xsl:param name="root"/>
 	<xsl:param name="filename"/>
@@ -48,7 +49,7 @@
 						<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:when>
-						<xsl:when test="$n='before'">
+						<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)-->
 							<xsl:apply-templates select="." mode="join">
 								<xsl:with-param name="namespaces" select="$namespaces"/>
@@ -90,7 +91,7 @@
 				</xsl:call-template>
 			</xsl:variable>
 			<xsl:variable name="ns" select="@id-namespace | namespace::* | exslt:node-set($nss)/*"/>
-			<xsl:copy><xsl:copy-of select="@*"/>
+			<xsl:copy><xsl:copy-of select="@*[name()!='schema']"/><xsl:call-template name="set-schema"/>
 				<xsl:apply-templates select="self::*[not(@id-namespace)]" mode="add-id-ns"/>
 				<xsl:for-each select="exslt:node-set($nss)/*"> <!-- add namespace definitions -->
 					<xsl:attribute name="xmlns:{name()}">
@@ -108,7 +109,7 @@
 		</xsl:when>
 		<xsl:otherwise> <!-- can't handle node-set() so put the namespaces in the document instead of the root element-->
 			<xsl:variable name="ns" select="@id-namespace | namespace::*"/>
-			<xsl:copy><xsl:copy-of select="@*"/>
+			<xsl:copy><xsl:copy-of select="@*[name()!='schema']"/><xsl:call-template name="set-schema"/>
 				<!-- no need to call is-content-filtered, it never will be from this element -->
 				<xsl:apply-templates select="*|comment()" mode="join">
 					<xsl:with-param name="namespaces" select="$ns"/>
@@ -193,6 +194,74 @@
 </xsl:template>
 
 
+<!-- schema handling -->
+
+<xsl:template name="set-schema">
+<xsl:attribute name="schema">
+	<xsl:apply-templates mode="my-schema" select="/SystemDefinition"/>
+</xsl:attribute>
+</xsl:template>
+
+<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>
+
+<xsl:template name="compare-version-list"><xsl:param name="list"/>
+	<xsl:variable name="cur" select="substring-before($list,' ')"/>
+	<xsl:variable name="remaining" select="substring-after($list,' ')"/>
+	<xsl:choose>
+		<xsl:when test="$remaining=''"><xsl:value-of select="$cur"/></xsl:when>
+		<xsl:otherwise>
+			<xsl:variable name="nextbig">
+				<xsl:call-template name="compare-version-list">
+					<xsl:with-param name="list" select="$remaining"/>
+				</xsl:call-template>
+			</xsl:variable>
+			<xsl:call-template name="compare-versions">
+				<xsl:with-param name="v1" select="$cur"/>
+				<xsl:with-param name="v2" select="$nextbig"/>
+			</xsl:call-template>
+		</xsl:otherwise>
+	</xsl:choose>
+</xsl:template>
+
+<xsl:template match="/SystemDefinition" mode="my-schema"><xsl:param name="biggest" select="@schema"/>
+	<xsl:variable name="linked" select="//*[(self::component or self::collection or self::package or self::layer) and @href]"/>
+	<xsl:choose>
+		<xsl:when test="not($linked)"> <!-- no need to go further -->
+			<xsl:call-template name="compare-versions">
+				<xsl:with-param name="v1" select="@schema"/>
+				<xsl:with-param name="v2" select="$biggest"/>
+			</xsl:call-template>
+		</xsl:when>
+		<xsl:otherwise>
+				<xsl:call-template name="compare-version-list">
+					<xsl:with-param name="list">
+						<xsl:for-each select="$linked">
+						<xsl:call-template name="compare-versions">
+							<xsl:with-param name="v1">
+								<xsl:apply-templates mode="my-schema" select="document(@href,.)/*"/>
+							</xsl:with-param>
+							<xsl:with-param name="v2" select="$biggest"/>
+						</xsl:call-template>
+						<xsl:text> </xsl:text>
+					</xsl:for-each>
+				</xsl:with-param>
+				</xsl:call-template>
+		</xsl:otherwise>
+	</xsl:choose>
+</xsl:template>
+
+
 <xsl:template match="unit" mode="join">	<xsl:param name="root"/><xsl:param name="filename"/><xsl:param name="data"/>
 	 <xsl:variable name="display">
 	 	<xsl:apply-templates select="$data" mode="filter">
@@ -371,7 +440,7 @@
 </xsl:template>
 
 
-<xsl:template match="@id|@before" mode="join">
+<xsl:template match="@id|@before|@replace" mode="join">
 	<xsl:param name="namespaces"/>
 	<!-- this will change the namespace prefixes for all IDs to match the root document -->
 	<xsl:variable name="ns">
--- a/sysdeftools/joinsysdef.pl	Thu May 06 16:24:41 2010 +0100
+++ b/sysdeftools/joinsysdef.pl	Thu May 06 16:31:38 2010 +0100
@@ -74,8 +74,9 @@
 
  if($path eq '') {$path = '/os/deviceplatformrelease/foundation_system/system_model/system_definition.xml'}
 
+($#ARGV == -1 ) && &help();
+my $sysdef = &abspath(shift);	# resolve the location of the root sysdef
 
-my $sysdef = &abspath(shift);	# resolve the location of the root sysdef
 
 
 
@@ -93,6 +94,9 @@
 my   $sysdefdoc = $parser->parsefile ($sysdef);
 
 
+my $maxschema = $sysdefdoc->getDocumentElement()->getAttribute('schema');	# don't check value, just store it.
+
+
 # find all the namespaces used in all trhe fragments and use that 
 # to set the namespaces ni the root element of the created doc
 #   should be able to optimise by only parsing each doc once and 
@@ -129,6 +133,10 @@
 	{
 	$docroot->setAttribute('id-namespace',$nsmap{''});
 	}
+
+$docroot->setAttribute('schema',$maxschema);	# output has the largest syntax version of all includes
+
+
 while(my($pre,$uri) = each(%nsmap))
 	{
 	$pre ne '' || next ;
@@ -220,7 +228,7 @@
 			my $file = &resolvePath($file,$link); 
 			if(-e $file)
 				{
-				&combineLink($node,&resolveURI($file,$link));
+				&combineLink($node,$file);
 				}
 			else
 				{
@@ -271,11 +279,14 @@
 				}
 			# if we're here we can just embed the file
 			# no processing logic is done! It's just embedded blindly
-			my  $metadoc = $parser->parsefile ($link);
-			my $item = $metadoc->getDocumentElement;
+			my $item;
+			eval {
+				my  $metadoc = $parser->parsefile ($link);
+				$item = $metadoc->getDocumentElement;
+			};
 			if(!$item)
 				{
-				print STDERR "Warning: Could not process metadata file: $link\n";
+				print STDERR "Error: Could not process metadata file: $link\n";
 				next; # do not alter children
 				}
 			$node->removeAttribute('href');
@@ -319,7 +330,7 @@
 	$getfromfile eq '' && return;  # already raised warning, no need to repeat
 	my  $doc = $parser->parsefile ($getfromfile);
 	my $item =&firstElement($doc->getDocumentElement);
-	$item || die "badly formatted $file";
+	$item || die "badly formatted $file";	
 	&fixIDs($item);
 	my %up = &atts($node);
 	my %down = &atts($item);
@@ -567,6 +578,7 @@
 			if(-e $link)
 				{
 				my  $doc = $parser->parsefile ($link);
+				&checkSyntaxVersion($doc->getDocumentElement->getAttribute('schema'));	# ensure we track we highest syntax number
 				my @docns = &namespaces($link,$doc->getDocumentElement);
 				undef $doc;
 				return (@res,@docns);
@@ -743,3 +755,43 @@
 	close CPP;
 	$? && die "Call to cpp produced an error";
 	}
+
+sub  checkSyntaxVersion
+	{ # check if supplied version number is greater than $maxschema
+	my $schema = shift;
+	my @max=split(/\./,$maxschema);
+	my @cur=split(/\./,$schema);
+	while(@max) 
+		{
+		($max[0] > $cur[0])  && return;		# max is bigger, do nothing
+		if($cur[0] > $max[0])
+			{
+			$maxschema=$schema;
+			return;
+			}
+		shift @max;
+		shift @cur;
+		}
+	# they are equal - do nothing
+	}
+
+sub help
+	{
+	my $name= $0; $name=~s,^.*[\\/],,;
+	print STDERR "usage: $name  [options...] sysdef\n\nvalid options are:\n",
+		"  -path\tspecifies the full system-model path to the file which is being processed. By default this is  \"/os/deviceplatformrelease/foundation_system/system_model/system_definition.xml\"\n",
+			"\t\tThis must be an absolute path if you're processing a root sysdef.\n",
+			"\t\tIf processing a pkgdef file, you can use \"./package_definition.xml\" to leave all links relative.\n\n",
+
+		"  -output\tspecifies the file to save the output to. If not specified this will write to stdout\n\n",
+
+		"  -config\tspecifies the name of an .hrh file in which the configuration data is acquired from. If not set, no confguration will be done.\n",
+			"\t\tIf it is set, all configuration metadata will be processed and stripped from the output, even if the confguration data is empty\n\n",
+		"  -I[path]\tspecifies the include paths to use when resolving #includes in the .hrh file. This uses the same syntax as cpp command uses: a captial \"I\" followed by the path with no space in between. Any number of these can be provided.\n";
+
+
+	exit(1);
+	}
+
+
+	
--- a/sysdeftools/mergesysdef-module.xsl	Thu May 06 16:24:41 2010 +0100
+++ b/sysdeftools/mergesysdef-module.xsl	Thu May 06 16:31:38 2010 +0100
@@ -42,7 +42,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>
@@ -59,8 +59,8 @@
 				<xsl:when test="contains(.,':')">
 					<xsl:value-of select="ancestor-or-self::*/namespace::*[name()=substring-before(current()/.,':')]"/>
 				</xsl:when>
-				<xsl:when test="/SystemDefinition/@id-namespace">
-					<xsl:value-of select="/SystemDefinition/@id-namespace"/>
+				<xsl:when test="ancestor::SystemDefinition/@id-namespace">
+					<xsl:value-of select="ancestor::SystemDefinition/@id-namespace"/>
 				</xsl:when>
 				<xsl:otherwise>
 					<xsl:value-of select="$defaultnamespace"/>
@@ -77,7 +77,7 @@
 			<xsl:when test="$nsdoc/namespace::*[.=$ns]">
 				<xsl:value-of select="concat(name($nsdoc/namespace::*[.=$ns]),':',$id)"/>
 			</xsl:when>
-			<xsl:when test="/SystemDefinition/@id-namespace=$ns">
+			<xsl:when test="ancestor::SystemDefinition/@id-namespace=$ns">
 				<xsl:variable name="myns">
 					<xsl:apply-templates mode="ns-prefix" select="$nsdoc">
 						<xsl:with-param name="ns" select="$ns"/>
@@ -93,7 +93,7 @@
 	</xsl:attribute>
 </xsl:template>
 
-<xsl:template match="/SystemDefinition" mode="ns-prefix">
+<xsl:template match="SystemDefinition" mode="ns-prefix">
 	<xsl:param name="ns"/> <!-- the namespace URI -->
 	<xsl:param name="pre"/> <!-- the preferred prefix to use if possbile -->
 	<xsl:param name="dontuse"/> <!-- space prefixed, separated and terminated list of namespace prefixes to not use -->
@@ -121,7 +121,7 @@
 
 <!--  need to make sure this handles <meta> correctly -->
 
-<xsl:template match="/SystemDefinition" mode="merge-models">
+<xsl:template match="SystemDefinition" mode="merge-models">
 	<xsl:param name="other"/>	<!-- the downstream SystemDefinition this is merged with -->
 	<xsl:param name="up" select="systemModel"/>	<!-- the element containing the origin @name used for any component from "this" model. -->
 	<xsl:param name="down" select="$other/systemModel"/> <!-- the element containing origin @name used for any component from $other model. -->
@@ -135,7 +135,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 +189,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 +199,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,6 +207,7 @@
 			<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>
 	</xsl:copy>
 </xsl:template>
@@ -357,12 +366,28 @@
 	<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]"/>
-	
-	
+
+	<xsl:choose>
+		<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"/>" <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"/>"</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::systemModel"/>			
+			</xsl:apply-templates>		
+		</xsl:when>
+		<xsl:otherwise>
+			<!-- remove this if it's in the list of stuff to be replaced-->
+
 	<!-- prev = the previous item before the current one (no metas, only named items)-->
 	<xsl:variable name="prev" select="preceding-sibling::*[@id][1]"/> 
 
@@ -410,9 +435,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,6 +467,7 @@
 					<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])]">
@@ -448,8 +481,11 @@
 			</xsl:otherwise>
 		</xsl:choose>
 	</xsl:copy>
+
+		</xsl:otherwise>
+	</xsl:choose>
 	
-	<xsl:if test="self::layer and not(following-sibling::layer)">
+	<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"/>
@@ -489,12 +525,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>
@@ -508,11 +542,27 @@
 	<xsl:copy-of select="."/>
 </xsl:template>
 
+
+<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 +572,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"/>
--- a/sysdeftools/mergesysdef.xsl	Thu May 06 16:24:41 2010 +0100
+++ b/sysdeftools/mergesysdef.xsl	Thu May 06 16:31:38 2010 +0100
@@ -77,7 +77,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 -->
 
 
 
--- a/sysdeftools/rootsysdef.pl	Thu May 06 16:24:41 2010 +0100
+++ b/sysdeftools/rootsysdef.pl	Thu May 06 16:31:38 2010 +0100
@@ -118,6 +118,10 @@
 	my   $fragment = $parser->parsefile ($_);
 	my $fdoc = $fragment->getDocumentElement();
 	my $topmost =&firstElement($fdoc);
+	if(!$topmost) {
+		print STDERR "$warning: $_ has no content. Skipping\n";
+		next;
+	}
 	my $type = $topmost->getTagName;
 	my $id = $topmost->getAttribute('id');
 	my ($localid,$ns) = &idns($topmost,$id);	
@@ -356,6 +360,7 @@
 	elsif($tag eq 'meta')
 		{
 		&fixHref($node,$file);
+		foreach my $child (@{$node->getChildNodes}) {$node->removeChild($child)} # can't have children
 		&processMeta($node);
 		next;
 		}
@@ -524,7 +529,7 @@
 sub guessIdInPath
 	{
 	my $id = shift;
-	my @path = reverse(split(/\//,shift));
+	my @path = reverse(split(/\//,$_[0]));
 	while(@path)
 		{
 		my $dir = shift(@path);
@@ -533,6 +538,12 @@
 			return ($id,@path);
 			}
 		}
+	print STDERR "$warning: Non-standard ID $id in $_[0]\n";
+	@path = reverse(split(/\//,$_[0]));
+	if($path[0] eq 'package_definition.xml')
+		{
+		return @path[1..$#path];
+		}
 	}
 
 
@@ -567,6 +578,7 @@
 	my $node = shift;
 	my $doc = $node->getOwnerDocument;
 	my $id = shift;
+	if($id eq '') {return}
 	my $fullid=$id;
 	my $contents = shift;
 	my $tag = &childTag($node->getTagName());
@@ -638,7 +650,7 @@
 		my $pre = $a;
 		if($pre=~s/^xmlns://)
 			{
-			if($node->getAttribute ($a) eq $ns)  {return $pre}
+			if($root->getAttribute ($a) eq $ns)  {return $pre}
 			}
 		}
 	die "ERROR: no namespace prefix defined for $ns";
@@ -672,6 +684,7 @@
 		$node->getParentNode->removeChild($node);
 		return;
 		}
+	foreach my $child (@{$node->getChildNodes}) {$node->removeChild($child)} # can't have children
 	if($output eq '')
 		{
 		$path=~s,^/?,file:///,;
@@ -695,6 +708,7 @@
 		{
 		$node->setAttribute('href',&relativeTo(&abspath($output),$file,'file'));
 		}
+	while(my $child =  $node->getFirstChild ) {$node->removeChild($child)}
 }