Added latest version of sysdeftools. See readme.txt for details on content. HighFidelityModel
authorBob Rosenberg <bob.rosenberg@nokia.com>
Tue, 06 Apr 2010 10:25:29 +0100
branchHighFidelityModel
changeset 151 84b123918d3f
parent 150 8d58b930d36e
child 152 5acf50bbb618
Added latest version of sysdeftools. See readme.txt for details on content.
sysdeftools/LICENSE.xalan
sysdeftools/docs/Changes for System Definition v2.0.0.doc
sysdeftools/docs/readme.txt
sysdeftools/filter-module.xsl
sysdeftools/filtering.xsl
sysdeftools/group/sysdeftools.mrp
sysdeftools/joinandparesysdef.xsl
sysdeftools/joinsysdef-module.xsl
sysdeftools/joinsysdef.pl
sysdeftools/joinsysdef.xsl
sysdeftools/mergesysdef-module.xsl
sysdeftools/mergesysdef.xsl
sysdeftools/readme.txt
sysdeftools/rootsysdef.pl
sysdeftools/sysdefdowngrade.xsl
sysdeftools/validate/checklinks.pl
sysdeftools/validate/modelcheck.xsl
sysdeftools/validate/test-model.xsl
sysdeftools/validate/validate-sysdef.xsl
sysdeftools/xalan.jar
sysdeftools/xercesImpl.jar
sysdeftools/xml-apis.jar
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysdeftools/LICENSE.xalan	Tue Apr 06 10:25:29 2010 +0100
@@ -0,0 +1,55 @@
+/*
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 1999 The Apache Software Foundation.  All rights 
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer. 
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. The end-user documentation included with the redistribution,
+ *    if any, must include the following acknowledgment:  
+ *       "This product includes software developed by the
+ *        Apache Software Foundation (http://www.apache.org/)."
+ *    Alternately, this acknowledgment may appear in the software itself,
+ *    if and wherever such third-party acknowledgments normally appear.
+ *
+ * 4. The names "Xalan" and "Apache Software Foundation" must
+ *    not be used to endorse or promote products derived from this
+ *    software without prior written permission. For written 
+ *    permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache",
+ *    nor may "Apache" appear in their name, without prior written
+ *    permission of the Apache Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation and was
+ * originally based on software copyright (c) 1999, Lotus
+ * Development Corporation., http://www.lotus.com.  For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ */
Binary file sysdeftools/docs/Changes for System Definition v2.0.0.doc has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysdeftools/docs/readme.txt	Tue Apr 06 10:25:29 2010 +0100
@@ -0,0 +1,2 @@
+The specification for the 3.0.0 and System Definition syntaxes can be found at
+http://developer.symbian.org/wiki/index.php/System_Definition
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysdeftools/filter-module.xsl	Tue Apr 06 10:25:29 2010 +0100
@@ -0,0 +1,123 @@
+<?xml version="1.0"?>
+<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
+	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 the logic to process the filter attribute in the system definition
+-->
+	<xsl:output method="xml" indent="yes"/>
+
+
+<!-- filters can only return hide or show -->
+
+<!-- filter-only =  item's @filter can only have items from the list
+	anything with no filters passes
+-->
+<xsl:template match="filter-only" mode="filter"><xsl:param name="item"/>
+	<xsl:if test="$item[@filter]">
+		<xsl:variable name="this" select="."/>
+		<xsl:variable name="my-filters">
+			<xsl:call-template name="filter-list">
+				<xsl:with-param name="f" select="$item/parent::component/@filter"/>
+			</xsl:call-template>
+			<xsl:call-template name="filter-list">
+				<xsl:with-param name="f" select="$item/@filter"/>
+			</xsl:call-template>
+		</xsl:variable>
+		<xsl:variable name="match">
+			<xsl:for-each select="exslt:node-set($my-filters)/*">
+				<xsl:if test="not($this/*[name()=name(current())  and @v=current()/@v])">x</xsl:if>
+			</xsl:for-each>
+		</xsl:variable>
+		<xsl:if test="$match!=''">hide</xsl:if>
+	</xsl:if>
+</xsl:template>
+
+
+
+<!-- filter-has =  item's @filter must have all filters in the list. ie it can have any other filters, but these must all be present	
+-->
+<xsl:template match="filter-has" mode="filter"><xsl:param name="item"/>
+	<xsl:if test="$item[(self::component or self::unit)  and not(unit/@filter or self::unit[not(../unit[@filter])])]">
+		<xsl:variable name="my-filters">
+			<xsl:call-template name="filter-list">
+				<xsl:with-param name="f" select="$item/parent::component/@filter"/>
+			</xsl:call-template>
+			<xsl:call-template name="filter-list">
+				<xsl:with-param name="f" select="$item/@filter"/>
+			</xsl:call-template>
+		</xsl:variable>
+		<xsl:variable name="match">
+			<xsl:for-each select="*">
+				<!-- 	if(f in this) {return true}  else if(!f in this) {return false} else {return !(f is positive)} -->
+				<xsl:choose>
+					<xsl:when test="exslt:node-set($my-filters)/*[name()=name(current()) and @v=current()/@v]"/> <!-- filter in item -->
+					<xsl:when test="exslt:node-set($my-filters)/*[name()!=name(current()) and @v=current()/@v]">x</xsl:when> <!-- !filter in item -->
+					<xsl:when test="self::filter">x</xsl:when> <!-- !(filter is positive) -->
+				</xsl:choose>
+			</xsl:for-each>
+		</xsl:variable>
+		<xsl:if test="$match!=''">hide</xsl:if>
+	</xsl:if>
+</xsl:template>
+
+<xsl:template match="filter-with" mode="filter"><xsl:param name="item"/>
+	<xsl:if test="$item[(self::component or self::unit)  and not(unit/@filter or self::unit[not(../unit[@filter])])]">
+		<xsl:variable name="my-filters">
+			<xsl:call-template name="filter-list">
+				<xsl:with-param name="f" select="$item/parent::component/@filter"/>
+			</xsl:call-template>
+			<xsl:call-template name="filter-list">
+				<xsl:with-param name="f" select="$item/@filter"/>
+			</xsl:call-template>
+		</xsl:variable>
+		<xsl:variable name="match">
+			<xsl:for-each select="*">
+				<xsl:if test="exslt:node-set($my-filters)/*[name()!=name(current()) and @v=current()/@v]">x</xsl:if> <!-- !filter in item -->
+			</xsl:for-each>
+		</xsl:variable>
+		<xsl:if test="$match!=''">hide</xsl:if>
+	</xsl:if>
+</xsl:template>
+
+
+
+<xsl:template name="filter-item"> <xsl:param name="f"/>
+	<!-- create an element for a given filter. If the filter's empty make nothing -->
+	<xsl:choose>
+		<xsl:when test="$f=''"/>
+		<xsl:when test="starts-with($f,'!')">
+				<not v="{substring($f,2)}"/>
+		</xsl:when>
+		<xsl:otherwise>
+				<filter v="{$f}"/>
+		</xsl:otherwise>
+	</xsl:choose>
+</xsl:template>
+
+<xsl:template name="filter-list"><xsl:param name="f"/>
+	<!-- turn a filter list into a set of elements (<filter> or <not>) with the attribute "v" containing the "absolute value" of the filter
+		filter="A,B,!C" becomes  <filter v="A"/><filter v="B"/><not v="C"/> 
+	  -->
+	<xsl:choose>
+		<xsl:when test="contains($f,',')">
+			<xsl:call-template name="filter-item"><xsl:with-param name="f" select="normalize-space(substring-before($f,','))"/></xsl:call-template>
+			<xsl:call-template name="filter-list">
+				<xsl:with-param name="f" select="substring-after($f,',')"/>
+			</xsl:call-template>
+		</xsl:when>
+		<xsl:otherwise>
+			<xsl:call-template name="filter-item"><xsl:with-param name="f" select="normalize-space($f)"/></xsl:call-template>
+		</xsl:otherwise>
+	</xsl:choose>
+</xsl:template>
+
+</xsl:stylesheet> 
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysdeftools/filtering.xsl	Tue Apr 06 10:25:29 2010 +0100
@@ -0,0 +1,276 @@
+<?xml version="1.0"?>
+<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
+	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:
+	Filter a sysdef in the 2.0 or 3.0 syntax
+-->
+<xsl:output method="xml" indent="yes"/>
+
+<xsl:param name="filter-type">only</xsl:param> <!-- only, has or with -->
+
+<xsl:param name="filter"/> <!-- comma-separated list -->
+
+<xsl:param name="addbuild" select="0"/> <!-- add a system build section that accepts everything -->
+
+
+<xsl:template match="node()|@*"><xsl:copy-of select="."/></xsl:template>
+<xsl:template match="*"><xsl:param name="data"/>
+	<xsl:copy>
+		<xsl:copy-of select="@*"/>
+		<xsl:apply-templates select="node()">
+			<xsl:with-param name="data" select="$data"/>
+		</xsl:apply-templates>
+	</xsl:copy>
+</xsl:template>
+
+<xsl:template match="component|unit"><xsl:param name="data"/> <!-- filterable items -->
+	 <xsl:variable name="display">
+	 	<xsl:apply-templates select="$data" mode="filter">
+			<xsl:with-param name="item" select="current()"/>
+		</xsl:apply-templates>
+	 </xsl:variable>
+	 
+	 <xsl:if test="$display != 'hide' "> <!-- if hide, remove completely from the output-->
+		<xsl:copy>
+			<xsl:copy-of select="@*"/>
+			<xsl:apply-templates select="node()">
+				<xsl:with-param name="data" select="$data"/>
+			</xsl:apply-templates>
+		</xsl:copy>
+	</xsl:if>
+</xsl:template>
+
+<xsl:template match="/SystemDefinition">
+	<xsl:variable name="f">
+		<xsl:element name="filter-{$filter-type}">
+			<xsl:call-template name="filter-list">
+				<xsl:with-param name="f" select="$filter"/>
+			</xsl:call-template>
+		</xsl:element>
+	</xsl:variable>
+	<xsl:choose>
+		<xsl:when test="starts-with(@schema,'3.0')"/> <!-- no DTD needed for 3.0 sysdef -->
+		<xsl:when test="$addbuild">
+			<xsl:call-template name="DTD-bld"/> <!-- insert 2.0.1 DTD w/sysbuild parts-->
+		</xsl:when>
+		<xsl:otherwise>
+			<xsl:call-template name="DTD"/> <!-- insert 2.0.1 DTD -->
+		</xsl:otherwise>
+	</xsl:choose>
+	<xsl:copy>
+		<xsl:copy-of select="@*"/>
+		<xsl:variable name="content"> <!-- save content for potential further processing -->
+			<xsl:apply-templates select="node()">
+				<xsl:with-param name="data" select="exslt:node-set($f)/*"/>
+			</xsl:apply-templates>
+		</xsl:variable>
+		<!-- just output content as is. We could create a template to remove any filtered out items, but so far there's no compelling need -->
+		<xsl:copy-of select="$content"/>  
+
+		<xsl:if test="$addbuild">
+			<SystemBuild schema="1.0.0">
+				<configuration name="any" description="text">
+					<xsl:attribute name="filter">
+						<xsl:for-each select="//@filter[not(.=following::*/@filter)]">
+							<xsl:value-of select="."/><xsl:if test="position()!=last()">,</xsl:if>
+						</xsl:for-each>
+					</xsl:attribute>
+					<xsl:for-each select="exslt:node-set($content)/systemModel/layer[descendant::unit]">
+						<!-- only include layers we know have units -->
+						<ref item="{@name}"/>
+					</xsl:for-each>
+				</configuration>
+			</SystemBuild>
+		</xsl:if>
+	</xsl:copy>
+</xsl:template>
+
+
+<xsl:include href="filter-module.xsl"/>
+
+<xsl:template name="DTD-bld">
+<xsl:text disable-output-escaping="yes"><![CDATA[<!DOCTYPE SystemDefinition [
+ <!ELEMENT SystemDefinition ( systemModel?, SystemBuild? )>
+ <!ATTLIST SystemDefinition
+  name CDATA #REQUIRED
+  schema CDATA #REQUIRED>
+ <!ELEMENT systemModel (layer+)>
+ <!ELEMENT layer (block* | collection*)*>
+ <!ATTLIST layer
+  name CDATA #REQUIRED
+  long-name CDATA #IMPLIED
+  levels NMTOKENS #IMPLIED
+  span CDATA #IMPLIED>
+ <!ELEMENT block (subblock* | collection*)*>
+ <!ATTLIST block
+  levels NMTOKENS #IMPLIED
+  span CDATA #IMPLIED
+  level NMTOKEN #IMPLIED
+  name CDATA #REQUIRED
+  long-name CDATA #IMPLIED>
+ <!ELEMENT subblock (collection)*>
+ <!ATTLIST subblock
+  name CDATA #REQUIRED
+  long-name CDATA #IMPLIED>
+ <!ELEMENT collection (component)*>
+ <!ATTLIST collection
+  name CDATA #REQUIRED
+  long-name CDATA #IMPLIED
+  level NMTOKEN #IMPLIED>
+ <!ELEMENT component (unit)*>
+ <!ATTLIST component
+  name CDATA #REQUIRED
+  long-name CDATA #IMPLIED
+  deprecated CDATA #IMPLIED
+  introduced CDATA #IMPLIED
+  contract CDATA #IMPLIED
+  plugin (Y|N) "N"
+  filter CDATA #IMPLIED
+  class NMTOKENS #IMPLIED
+  supports CDATA #IMPLIED
+  purpose ( optional | mandatory | development ) "optional">
+ <!ELEMENT unit EMPTY>
+ <!ATTLIST unit
+  mrp CDATA #IMPLIED
+  filter CDATA #IMPLIED
+  bldFile CDATA #IMPLIED
+  root CDATA #IMPLIED
+  version NMTOKEN #IMPLIED
+  prebuilt NMTOKEN #IMPLIED
+  late (Y|N) #IMPLIED
+  priority CDATA #IMPLIED>
+ <!ELEMENT SystemBuild (option* | target+ | targetList+ | list+ | configuration+)*>
+ <!ATTLIST SystemBuild schema CDATA #REQUIRED>
+ <!ELEMENT list (ref+)>
+ <!ATTLIST list
+  name ID #REQUIRED
+  description CDATA #REQUIRED>
+ <!ELEMENT ref EMPTY>
+ <!ATTLIST ref item CDATA #REQUIRED>
+ <!ELEMENT targetList EMPTY>
+ <!ATTLIST targetList
+  name ID #REQUIRED
+  description CDATA #REQUIRED
+  target IDREFS #REQUIRED>
+ <!ELEMENT target EMPTY>
+ <!ATTLIST target
+  name ID #REQUIRED
+  abldTarget CDATA #REQUIRED
+  description CDATA #REQUIRED>
+ <!ELEMENT option EMPTY>
+ <!ATTLIST option
+  name ID #REQUIRED
+  abldOption CDATA #REQUIRED
+  description CDATA #REQUIRED
+  enable (Y | N ) #REQUIRED>
+ <!ELEMENT configuration (listRef+ | ref+ | task+)*>
+ <!ATTLIST configuration
+  name ID #REQUIRED
+  description CDATA #REQUIRED
+  filter CDATA #REQUIRED>
+ <!ELEMENT task (listRef* , (buildLayer | specialInstructions))>
+ <!ELEMENT listRef EMPTY>
+ <!ATTLIST listRef list CDATA #REQUIRED>
+ <!ELEMENT buildLayer EMPTY>
+ <!ATTLIST buildLayer
+  command CDATA #REQUIRED
+  targetList IDREFS #IMPLIED
+  unitParallel (Y | N ) #REQUIRED
+  targetParallel (Y | N ) "N">
+ <!ELEMENT specialInstructions EMPTY>
+ <!ATTLIST specialInstructions
+  name CDATA #REQUIRED
+  cwd CDATA #REQUIRED
+  root CDATA #IMPLIED
+  command CDATA #REQUIRED>
+]>
+]]></xsl:text>
+</xsl:template>
+
+<xsl:template name="DTD">
+<xsl:text disable-output-escaping="yes"><![CDATA[<!DOCTYPE SystemDefinition [
+<!ELEMENT SystemDefinition ( systemModel )>
+<!ATTLIST SystemDefinition
+  name CDATA #REQUIRED
+  schema CDATA #REQUIRED
+>
+<!-- all paths are relative to the environment variable specified by the root attribute, or SOURCEROOT if not.  -->
+
+<!-- System Model Section of DTD -->
+<!ELEMENT systemModel (layer+)>
+
+<!ELEMENT layer (block* | collection*)*>
+<!-- Kernel Services, Base Services, OS Services, Etc -->
+<!ATTLIST layer
+  name CDATA #REQUIRED
+  long-name CDATA #IMPLIED
+  levels NMTOKENS #IMPLIED
+  span CDATA #IMPLIED
+>
+
+<!ELEMENT block (subblock* | collection*)*>
+ <!-- Generic OS services, Comms Services, etc -->
+<!ATTLIST block
+  levels NMTOKENS #IMPLIED
+  span CDATA #IMPLIED
+  level NMTOKEN #IMPLIED
+  name CDATA #REQUIRED
+  long-name CDATA #IMPLIED
+>
+
+<!ELEMENT subblock (collection)*>
+<!-- Cellular Baseband Services, Networking Services, etc -->
+<!ATTLIST subblock
+  name CDATA #REQUIRED
+  long-name CDATA #IMPLIED
+>
+
+<!ELEMENT collection (component)*>
+<!-- Screen Driver, Content Handling, etc -->
+<!ATTLIST collection
+  name CDATA #REQUIRED
+  long-name CDATA #IMPLIED
+  level NMTOKEN #IMPLIED
+>
+
+<!ELEMENT component (unit)*>
+<!-- contains units or is a  package or prebuilt -->
+<!ATTLIST component
+  name CDATA #REQUIRED
+  long-name CDATA #IMPLIED
+  deprecated CDATA #IMPLIED
+  introduced CDATA #IMPLIED
+  contract CDATA #IMPLIED
+  plugin (Y|N) "N"
+  filter CDATA #IMPLIED
+  class NMTOKENS #IMPLIED
+  supports CDATA #IMPLIED
+  purpose ( optional | mandatory | development ) "optional"
+>
+
+<!ELEMENT unit EMPTY >
+<!-- must be buildable (bld.inf) -->
+<!-- bldFile  may someday be removed in favour of mrp -->
+<!ATTLIST unit
+  mrp CDATA #IMPLIED
+  filter CDATA #IMPLIED
+  bldFile CDATA #IMPLIED
+  root CDATA #IMPLIED
+  version NMTOKEN #IMPLIED
+  prebuilt NMTOKEN #IMPLIED
+  late (Y|N) #IMPLIED
+  priority CDATA #IMPLIED
+>
+]>
+]]></xsl:text>
+</xsl:template>
+</xsl:stylesheet>	
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysdeftools/group/sysdeftools.mrp	Tue Apr 06 10:25:29 2010 +0100
@@ -0,0 +1,7 @@
+component	sysdeftools
+
+source	\sf\os\buildtools\bldsystemtools\sysdeftools\
+notes_source	\component_defs\release.src
+
+
+ipr T 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysdeftools/joinandparesysdef.xsl	Tue Apr 06 10:25:29 2010 +0100
@@ -0,0 +1,41 @@
+<?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:
+	Create a stand-alone sysdef from a linked set of fragments, paring down to just a set of items of the desired rank.
+-->
+ 	<xsl:output method="xml" indent="yes"/>
+
+	<!-- comma-separated list of IDs in the literal from as the document they appear in (ie same namespace prefix) -->
+<xsl:param name="pare"/>		
+
+
+	<!-- the rank item to pare down. This will remove any item of that rank EXCEPT those in $pare -->
+<xsl:param name="rank">package</xsl:param>
+
+<xsl:variable name="pare-list" select="concat(',',translate(normalize-space($pare),' ',','),',')"/> <!-- accept spaces in pare. Pad with commas to make computing easier -->
+
+<xsl:include href="joinsysdef.xsl"/>  
+
+<xsl:template match="/SystemDefinition[systemModel]">
+	<xsl:apply-templates select="." mode="join">
+		<xsl:with-param name="filename" select="$path"/>
+		<xsl:with-param name="data" select="current()"/> <!-- just has to be non-empty -->
+	</xsl:apply-templates>
+</xsl:template>
+
+<xsl:template match="*" mode="filter"> <!-- use this to strip out the unwanted items -->
+	<xsl:param name="item" />
+	<xsl:if test="$rank=name($item) and not(contains($pare-list,concat(',',$item/@id,',')))">hide</xsl:if>
+</xsl:template>
+
+</xsl:stylesheet>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysdeftools/joinsysdef-module.xsl	Tue Apr 06 10:25:29 2010 +0100
@@ -0,0 +1,534 @@
+<?xml version="1.0"?>
+ <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
+	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 the logic to join a system definition file
+-->
+	<!-- save SF namespace as a constant to avoid the risk of typos-->
+ <xsl:variable name="defaultns">http://www.symbian.org/system-definition</xsl:variable>
+ 
+<!-- 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:template>
+
+
+<xsl:template match="/SystemDefinition[@schema='3.0.0' and count(*)=1]" mode="join">
+	<xsl:param name="origin" select="/.."/>
+	<xsl:param name="root"/>
+	<xsl:param name="filename"/>
+	<xsl:param name="namespaces"/>
+	<xsl:param name="data" select="/.."/>
+	<xsl:choose>
+		<xsl:when test="$origin">	<!-- this sysdef fragment was linked from a parent sysdef -->
+			<xsl:for-each select="*"> <!-- can be only one -->
+				<xsl:variable name="upid"><xsl:apply-templates select="$origin/@id" mode="my-id"/></xsl:variable>		<!-- namespaceless ID of this in parent doc -->
+				<xsl:variable name="id"><xsl:apply-templates select="@id" mode="my-id"/></xsl:variable>						<!-- namespaceless ID of this here -->
+				<xsl:variable name="upns"><xsl:apply-templates select="$origin/@id" mode="my-namespace"/></xsl:variable>	<!-- ID's namespace in parent doc -->
+				<xsl:variable name="ns"><xsl:apply-templates select="@id" mode="my-namespace"/></xsl:variable>	<!-- ID's namespace -->
+				<xsl:if test="$id!=$upid or $ns!=$upns">
+					<xsl:message terminate="yes">ERROR: Linked ID "<xsl:value-of select="$id"/>" (<xsl:value-of select="$ns"/>) must match linking document "<xsl:value-of select="$upid"/>" (<xsl:value-of select="$upns"/>)</xsl:message>
+				</xsl:if>
+				<!-- copy any attributes not already defined (parent doc overrides child doc)-->
+				<xsl:for-each select="@*">
+					<xsl:variable name="n" select="name()"/>
+					<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:when>
+						<xsl:when test="$n='before'">
+							<!-- 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"/>
+							</xsl:apply-templates>
+						</xsl:when> 
+						<xsl:otherwise><xsl:copy-of select="."/></xsl:otherwise> <!-- just copy anything else -->
+					</xsl:choose>
+				</xsl:for-each>
+				<xsl:copy-of select="../namespace::*[not(.=$namespaces)]"/> <!-- set any namespaces not already set (they should all alreayd be, but some XSLT processors are quirky) -->
+			 	<xsl:apply-templates select="$data" mode="overlay-attributes">
+					<xsl:with-param name="item" select="current()"/>
+				</xsl:apply-templates>
+				<xsl:variable name="content">									
+					<xsl:apply-templates select="*|comment()" mode="join">
+						<xsl:with-param name="root" select="$root"/>
+						<xsl:with-param name="filename" select="$filename"/>
+						<xsl:with-param name="data" select="$data"/>
+						<xsl:with-param name="namespaces" select="$namespaces | ../namespace::*[not(.=$namespaces)]"/>
+					</xsl:apply-templates>
+				</xsl:variable>
+				<xsl:apply-templates select="." mode="is-content-filtered"> <!-- optionally add filtered="yes" if some content has been removed -->
+					<xsl:with-param name="content" select="$content"/>
+				</xsl:apply-templates>
+			 	<xsl:apply-templates select="$data" mode="overlay-meta">
+					<xsl:with-param name="item" select="current()"/>
+				</xsl:apply-templates>
+				<xsl:copy-of select="$content"/>
+			</xsl:for-each>
+		</xsl:when>
+		<xsl:when test="function-available('exslt:node-set')"> <!-- this is the root element of a root sysdef -->
+			<!--try to put all namespaces in root element -->
+			<xsl:variable name="nss">
+				<!-- contains node set of namespaces to add to root element.
+					May panic if there are too many single-letter namespaces and this can't create a new one -->
+				<xsl:call-template name="needed-namespaces">
+					<xsl:with-param name="foundns">
+						<xsl:apply-templates select="//*[(self::component or self::collection or self::package or self::layer) and @href]" mode="scan-for-namespaces"/>
+					</xsl:with-param>
+				</xsl:call-template>
+			</xsl:variable>
+			<xsl:variable name="ns" select="@id-namespace | namespace::* | exslt:node-set($nss)/*"/>
+			<xsl:copy><xsl:copy-of select="@*"/>
+				<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()}">
+						<xsl:value-of select="."/>
+					</xsl:attribute>
+				</xsl:for-each>
+				<!-- 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"/>
+					<xsl:with-param name="root" select="$root"/>
+					<xsl:with-param name="data" select="$data"/>
+					<xsl:with-param name="filename" select="$filename"/>
+				</xsl:apply-templates>
+			</xsl:copy>
+		</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="@*"/>
+				<!-- 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"/>
+					<xsl:with-param name="root" select="$root"/>
+					<xsl:with-param name="data" select="$data"/>
+					<xsl:with-param name="filename" select="$filename"/>
+				</xsl:apply-templates>
+			</xsl:copy>
+		</xsl:otherwise>
+	</xsl:choose>
+</xsl:template>
+
+<xsl:template match="*" mode="scan-for-namespaces"/> <!-- just in case of errors, consider replacing by terminate -->
+<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: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::* | @id-namespace">
+			<xsl:value-of select="concat(name(),' ',.,'&#xa;')"/>
+		</xsl:for-each>
+	</xsl:for-each>			
+</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 -->
+		<xsl:variable name="remainder" select="substring-after($foundns,'&#xa;')"/>
+		<xsl:variable name="newprefix">
+			<xsl:if test="not(contains(concat('&#xa;',$remainder),concat('&#xa;',$line,'&#xa;'))) and
+				not(//namespace::*[.=$name] or @id-namespace[.=$name] or (not(@id-namespace) and $defaultns=$name))">
+						<xsl:apply-templates select="." mode="ns-prefix">
+							<xsl:with-param name="ns" select="$name"/>
+							<xsl:with-param name="pre" select="substring-before($line,' ')"/>
+							<xsl:with-param name="dontuse" select="$usedpre"/>
+						</xsl:apply-templates>
+			</xsl:if>
+		</xsl:variable>
+		<xsl:if test="$newprefix!=''">
+			<!-- can treat this as if it were a namespace node -->
+			<xsl:element name="{$newprefix}">
+				<xsl:value-of select="$name"/>
+			</xsl:element>
+		</xsl:if>
+		<xsl:if test="$remainder!=''">
+			<xsl:call-template name="needed-namespaces">
+				<xsl:with-param name="foundns" select="$remainder"/>
+				<xsl:with-param name="usedpre" select="concat($usedpre,' ',$newprefix,' ')"/>
+			</xsl:call-template>
+		</xsl:if>
+	</xsl:if>
+</xsl:template>
+
+<xsl:template match="/SystemDefinition" mode="ns-prefix">
+	<!-- should be able to replace this with mechanism that uses the XSLT processor's own ability to generate namespaces -->
+	<xsl:param name="ns"/>
+	<xsl:param name="pre"/>
+	<xsl:param name="dontuse"/>
+	<xsl:param name="chars">ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz</xsl:param>
+	<xsl:variable name="name" select="substring(substring-after($ns,'http://www.'),1,1)"/>
+	<xsl:choose>
+		<xsl:when test="$pre!='' and $pre!='id-namespace' and not(//namespace::*[name()=$pre]) and not(contains($dontuse,concat(' ',$pre,' ')))">
+			<xsl:value-of select="$pre"/>
+		</xsl:when>
+		<xsl:when test="$ns='' and $chars=''">
+			<xsl:message terminate="yes">ERROR: Cannot create namespace prefix for downstream default namespace in <xsl:value-of select="*/@id"/></xsl:message>
+		</xsl:when>
+		<xsl:when test="$name!='' and not(contains($dontuse,concat(' ',$name,' ')))"><xsl:value-of select="$name"/></xsl:when>
+		<xsl:when test="namespace::*[name()=substring($chars,1,1)] or contains($dontuse,concat(' ',substring($chars,1,1),' '))">
+			<xsl:apply-templates mode="ns-prefix">
+				<xsl:with-param name="chars" select="substring($chars,2)"/>
+			</xsl:apply-templates>
+		</xsl:when>
+		<xsl:otherwise>
+			<xsl:value-of select="substring($chars,1,1)"/>
+		</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">
+			<xsl:with-param name="item" select="current()"/>
+		</xsl:apply-templates>
+	 </xsl:variable>
+	 
+	 <xsl:if test="$display != 'hide' "> <!-- if hide, remove completely from the output-->	 
+		<xsl:element name="{name()}">
+			<xsl:apply-templates select="@*" mode="join">
+				<xsl:with-param name="root" select="$root"/>
+				<xsl:with-param name="filename" select="$filename"/>
+			</xsl:apply-templates>
+		</xsl:element>
+	</xsl:if>
+</xsl:template>
+
+<!-- override mode="meta" to translate metadata sections. By default, include -->
+<xsl:template match="meta" priority="2" mode="join"><xsl:param name="data"/>
+	 <xsl:variable name="display">
+	 	<xsl:apply-templates select="$data" mode="filter">
+			<xsl:with-param name="item" select="current()"/>
+		</xsl:apply-templates>
+	 </xsl:variable>
+	 
+	<xsl:if test="$display != 'hide' "> <!-- if hide, remove completely from the output-->	
+		<xsl:apply-templates select="." mode="meta"> 
+			<xsl:with-param name="display" select="$display"/>
+			<xsl:with-param name="data" select="$data"/>
+		</xsl:apply-templates>
+	</xsl:if>
+</xsl:template>
+
+<xsl:template match="meta[@rel='link-mapping']" priority="3" mode="join"/> <!--these are only used in the joining process, so remove from output -->
+
+
+<xsl:template match="*" mode="join">
+	<xsl:param name="root"/><xsl:param name="filename"/><xsl:param name="namespaces"/><xsl:param name="data"/>
+	<!-- get attribtues from overlay -->
+	<!-- test for presence, if filtered out, just return -->
+	<!-- test for children, if it has some, but they're filtered out, either return or leave as empty, dependening on filter rule
+		if had items and now has none, options:
+			still has meta: keep / delete
+			still has comments: keep / delete 
+	 -->
+	 <xsl:variable name="display">
+	 	<xsl:apply-templates select="$data" mode="filter">
+			<xsl:with-param name="item" select="current()"/>
+		</xsl:apply-templates>
+	 </xsl:variable>
+	 
+	 <xsl:if test="$display != 'hide' "> <!-- if hide, remove completely from the output-->
+		 <xsl:variable name="href">
+		 	<xsl:apply-templates select="." mode="link">
+				<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"/>
+			</xsl:apply-templates>
+			<xsl:if test="$display != '' ">
+				<!-- custom attribute to indicate how this is to be represented. Blank indicates normal, hide removes from the output (see above), anything else is put in the attribute --> 
+				<xsl:attribute name="display"><xsl:value-of select="$display"/></xsl:attribute>
+			</xsl:if>
+		 	<xsl:apply-templates select="$data" mode="overlay-attributes">
+				<xsl:with-param name="item" select="current()"/>
+			</xsl:apply-templates>			
+			<xsl:choose>
+				<xsl:when test="$href !='' ">
+					<xsl:variable name="prefixmap" select="ancestor::SystemDefinition/*/meta[@rel='link-mapping']/map-prefix[starts-with($href,@link)]"/>
+					<xsl:variable name="origin" select="."/>
+					<xsl:apply-templates select="document($href,.)/*" mode="join">
+						<xsl:with-param name="origin" select="$origin"/>
+						<xsl:with-param name="data" select="$data"/>
+						<xsl:with-param name="namespaces" select="$namespaces"/>
+						<xsl:with-param name="filename">
+							<xsl:call-template name="joinpath">
+								<xsl:with-param name="file" select="$filename"/>
+								<xsl:with-param name="rel">
+									<xsl:choose>
+										<xsl:when test="$prefixmap">
+											<xsl:value-of select="$prefixmap/@to"/>
+											<xsl:value-of select="substring-after($href,$prefixmap/@link)"/>
+										</xsl:when>
+										<xsl:otherwise>
+											<xsl:value-of select="$href"/>
+										</xsl:otherwise>
+									</xsl:choose>								
+								 </xsl:with-param>
+							</xsl:call-template>					
+						</xsl:with-param>
+						<xsl:with-param name="root">
+							<xsl:value-of select="$root"/>/<xsl:call-template name="lastbefore">
+								<xsl:with-param name="string" select="$href"/>
+							</xsl:call-template>
+						</xsl:with-param>
+					</xsl:apply-templates> 
+				</xsl:when>
+				<xsl:otherwise>
+					<xsl:variable name="content">
+						<xsl:apply-templates select="*|comment()" mode="join">
+							<xsl:with-param name="root" select="$root"/>
+							<xsl:with-param name="filename" select="$filename"/>
+							<xsl:with-param name="namespaces" select="$namespaces"/>
+							<xsl:with-param name="data" select="$data"/>
+						</xsl:apply-templates>
+					</xsl:variable>
+					<xsl:apply-templates select="." mode="is-content-filtered"> <!-- add filtered="yes" if some content has been removed -->
+						<xsl:with-param name="content" select="$content"/>
+					</xsl:apply-templates>
+				 	<xsl:apply-templates select="$data" mode="overlay-meta">
+						<xsl:with-param name="item" select="current()"/>
+					</xsl:apply-templates>
+					<xsl:copy-of select="$content"/>
+				</xsl:otherwise>
+			</xsl:choose>
+		</xsl:element>
+	</xsl:if>
+</xsl:template>
+
+<!-- By default, do nothing. Can override template to add filtered="yes" if need to track what's a placeholder and what's been filtered 
+	implement with param name="content"
+-->
+<xsl:template mode="is-content-filtered" match="*" priority="-2"/>
+
+
+<xsl:template match="@mrp[starts-with(.,'/')] | @bldFile[starts-with(.,'/')] | @base[starts-with(.,'/')]" mode="join">
+	<xsl:copy-of select="."/>
+</xsl:template>
+
+
+<xsl:template match="@mrp|@bldFile|@base" mode="join">	<xsl:param name="root"/><xsl:param name="filename"/>
+	<xsl:attribute name="{name()}">
+		<xsl:call-template name="joinpath">
+			<xsl:with-param name="file" select="$filename"/>
+			<xsl:with-param name="rel" select="."/>
+		</xsl:call-template>	
+	</xsl:attribute>	
+</xsl:template>
+
+
+<xsl:template match="@href" mode="join"/> <!--never copy this into the generated doc, that's the whole point of this module -->
+
+<xsl:template match="@*" mode="my-namespace"> <!-- the namespace of an ID -->
+	<xsl:choose>
+		<xsl:when test="contains(.,':')">
+			<xsl:value-of select="ancestor::*/namespace::*[name()=substring-before(current(),':')]"/>
+		</xsl:when>
+		<xsl:when test="/SystemDefinition/@id-namespace">
+			<xsl:value-of select="/SystemDefinition/@id-namespace"/>
+		</xsl:when>
+		<xsl:otherwise>
+			<xsl:value-of select="$defaultns"/>
+		</xsl:otherwise>
+	</xsl:choose>
+</xsl:template>
+
+
+<xsl:template match="@*" mode="my-id"> <!-- the ID with namespace prefix removed -->
+	<xsl:choose>
+		<xsl:when test="contains(.,':')">
+			<xsl:value-of select="substring-after(.,':')"/>
+		</xsl:when>
+		<xsl:otherwise>
+			<xsl:value-of select="."/>
+		</xsl:otherwise>
+	</xsl:choose>
+</xsl:template>
+
+<xsl:template match="*" mode="err-path">
+<xsl:if test="../@id">
+	<xsl:apply-templates select=".." mode="err-path"/>/</xsl:if>
+<xsl:value-of select="@id"/>
+</xsl:template>
+
+
+<xsl:template match="@id|@before" mode="join">
+	<xsl:param name="namespaces"/>
+	<!-- this will change the namespace prefixes for all IDs to match the root document -->
+	<xsl:variable name="ns">
+		<xsl:apply-templates select="." mode="my-namespace"/>
+	</xsl:variable>
+	<xsl:if test="$ns=''">
+		<xsl:message terminate="yes">ERROR: Could not find namespace for <xsl:value-of select="name()"/> "<xsl:value-of select="."/>" in <xsl:apply-templates select="../.." mode="err-path"/>
+		<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-prefix']) 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)-->
+			<xsl:value-of select="."/>
+		</xsl:when>
+		<xsl:when test="$prefix='' and $ns=$defaultns"/> <!-- no prefix and it's the default --> 
+		<xsl:when test="$prefix!=''">			<!-- just change the prefix -->
+			<xsl:value-of select="concat($prefix,':')"/>
+		</xsl:when>
+		<xsl:otherwise>
+		<xsl:message terminate="yes">ERROR: Joining error in resolving namespace for <xsl:value-of select="name()"/> "<xsl:value-of select="."/>" in <xsl:apply-templates select="../.." mode="err-path"/>
+		<xsl:text>&#xa;</xsl:text></xsl:message>
+		</xsl:otherwise>
+	</xsl:choose>
+		<xsl:apply-templates select="." mode="my-id"/>
+	</xsl:attribute>
+</xsl:template>
+
+
+
+<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>
+
+<!-- overridable templates follow -->
+
+
+<xsl:template match="*" mode="filter" priority="-9"/> <!-- by default show --> 
+<xsl:template match="*" mode="overlay-attributes" priority="-9"/> <!-- by default do nothing --> 
+<xsl:template match="*" mode="overlay-meta" priority="-9"/> <!-- by default do nothing --> 
+<xsl:template match="/SystemDefinition" mode="add-id-ns" priority="-9"/> <!-- some tools may have an easier job if this were always present, but, by default, assume it can just stay implied -->
+
+<xsl:template match="*" mode="link" priority="-1"> <!-- can be overriden to allow custom changes to href values --> 
+<xsl:value-of select="@href"/>
+</xsl:template>
+
+
+<xsl:template match="*" mode="meta" priority="-9"><xsl:param name="data"/><xsl:param name="display"/>
+	<xsl:element name="{name()}">
+		<xsl:copy-of select="@*[name()!='href']"/> <!-- copy all attributes as is, always drop href -->
+		<xsl:choose>
+			<xsl:when test="$display='local' and @href and contains(@href,':') and not(starts-with(@href,'file:'))">
+				<!-- non-local URL: only want local URLs, so keep href as is-->
+				<xsl:copy-of select="@href"/> 
+			</xsl:when>
+			<xsl:when test="@href">
+				<xsl:copy-of select="document(@href,.)/*"/> 
+			</xsl:when>
+			<xsl:otherwise>
+				<xsl:copy-of select="*|comment()"/>
+			</xsl:otherwise>
+		</xsl:choose>
+	</xsl:element>
+</xsl:template>
+
+
+</xsl:stylesheet>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysdeftools/joinsysdef.pl	Tue Apr 06 10:25:29 2010 +0100
@@ -0,0 +1,748 @@
+# Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+# All rights reserved.
+# This component and the accompanying materials are made available
+# under the terms of "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:
+#
+#!/usr/bin/perl
+
+use strict;
+
+
+use FindBin;		# for FindBin::Bin
+use lib $FindBin::Bin;
+use lib "$FindBin::Bin/lib";
+
+use Cwd;
+use Cwd 'abs_path';
+use Getopt::Long;
+use File::Basename;
+use File::Spec;
+use XML::DOM;
+
+my $output;
+my $path;
+my $config;
+my @includes;
+my %defineParams;
+my %defines;
+my $defaultns = 'http://www.symbian.org/system-definition';	# needed if no DTD
+
+my @newarg;
+foreach my $a (@ARGV)
+	{ #extract all -I parameters from the parameter list 
+	if($a=~s/^-I//)
+		{
+		push(@includes,$a);
+		}
+	else
+		{
+		push(@newarg,$a);
+		}
+	}
+@ARGV=@newarg;
+
+# need to add options for controlling which metas are filtered out and which are included inline
+GetOptions
+	(
+	 'path=s' => \$path,
+	'output=s' => \$output,
+	'config=s' => \$config
+	);
+
+# -path specifies the full system-model path to the file which is being processed. 
+#	This must be an absolute path if you're processing a root sysdef.
+#	If processing a pkgdef file, you can use "./package_definition.xml" to leave all links relative. Though I can't really see the use case for this.
+
+# -output specifies the file to save the output to. If not specified this will write to stdout
+
+# -config specifies the name of an .hrh file in which the configuration data is acquired from. If not set, no confguration will be done.
+
+# -I[path] specifies the include paths to use when resolving #includes in the .hrh file. Same syntax as cpp command uses. Any number of these can be provided.
+
+
+# if config is not set, no confguration will be done.
+# If it is set, all configuration metadata will be processed and stripped from the output, even if the confguration data is empty
+
+ if($path eq '') {$path = '/os/deviceplatformrelease/foundation_system/system_model/system_definition.xml'}
+
+
+my $sysdef = &abspath(shift);	# resolve the location of the root sysdef
+
+
+
+# rootmap is a mapping from the filesystem to the paths in the doc
+my %rootmap = &rootMap($path,$sysdef);	
+my %nsmap;
+my %urimap;
+
+if($config ne '') 
+	{ # run cpp to get all #defines
+	&getDefines($config);
+	}
+
+my $parser = new XML::DOM::Parser;
+my   $sysdefdoc = $parser->parsefile ($sysdef);
+
+
+# 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 
+#	maybe skipping the contends of <meta>
+my @nslist = &namespaces($sysdef,$sysdefdoc->getDocumentElement());
+
+
+while(@nslist)
+	{
+	my $uri = shift(@nslist);
+	my $prefix =shift(@nslist);
+	if($prefix eq 'id namespace'){$prefix=''}
+	if(defined $urimap{$uri}) {next} # already done this uri
+	$urimap{$uri} = $prefix;
+	if($nsmap{$prefix})
+		{ # need a new prefix for this, guess from the URI (for readability)
+		if($uri=~/http:\/\/(www\.)?([^.\/]+)\./) {$prefix = $2}
+		my $i=0;
+		while($nsmap{$prefix})
+			{ # still no prefix, just make up 
+			$prefix="ns$i";
+			$i++;
+			# next line not really necessary, but it's a good safety to stop infinite loops
+			$i eq 1000 && die "cannot create namespace prefix for $uri";
+			}
+		}
+	$nsmap{$prefix}=$uri;
+	}
+
+my $docroot =  $sysdefdoc->getDocumentElement;
+
+my $ns = $docroot->getAttribute('id-namespace');
+if(!$ns && $nsmap{''})
+	{
+	$docroot->setAttribute('id-namespace',$nsmap{''});
+	}
+while(my($pre,$uri) = each(%nsmap))
+	{
+	$pre ne '' || next ;
+	$docroot->setAttribute("xmlns:$pre",$uri);
+	}
+
+&walk($sysdef,$docroot);	# process the XML
+
+
+# print to file or stdout
+if($output eq '') 
+	{
+	print $sysdefdoc->toString;
+	}
+else
+	{
+	$sysdefdoc->printToFile($output);
+	}
+
+ 
+sub abspath
+	{ 	# normalize the path into an absolute one
+	my  ($name,$path) = fileparse($_[0]);
+	$path=~tr,\\,/,;
+	if( -e $path)
+		{
+		return abs_path($path)."/$name";
+		}
+	my @dir = split('/',$_[0]);
+	my @new;
+	foreach my $d (@dir)
+		{
+		if($d eq '.') {next}
+		if($d eq '..')
+			{
+			pop(@new);
+			next;
+			}
+		push(@new,$d)
+		}
+	return join('/',@new);
+	}
+
+sub rootMap {
+	my @pathdirs = split(/\//,$_[0]);
+	my @rootdirs = split(/\//,$_[1]);
+
+	while(lc($rootdirs[$#rootdirs])  eq lc($pathdirs[$#pathdirs])  )
+		{
+		pop(@rootdirs);
+		pop(@pathdirs);
+		}
+	return (join('/',@rootdirs)  => join('/',@pathdirs) );
+	}
+
+sub rootMapMeta {
+	# find all the explict path mapping from the link-mapping metadata
+	my $node = shift;
+	foreach my $child (@{$node->getChildNodes})
+			{
+			if ($child->getNodeType==1 && $child->getTagName eq 'map-prefix')
+				{
+				my $from = $child->getAttribute('link');
+				my $to = $child->getAttribute('to');		# optional, but blank if not set
+				$rootmap{$from} = $to;
+				}
+			}
+	# once this is processed we have no more need for it. Remove from output
+	$node->getParentNode->removeChild($node);
+	}
+
+
+sub walk
+	{ 	# walk through the doc, resolving all links
+	my $file = shift;
+	my $node = shift;
+	my $type = $node->getNodeType;
+	if($type!=1) {return}
+	my $tag = $node->getTagName;
+	if($tag=~/^(layer|package|collection|component)$/ )
+		{
+		if($file eq $sysdef)
+			{
+			&fixIDs($node);	# normalise all IDs in the root doc. Child docs are handled elsewhere.
+			}
+		my $link= $node->getAttribute('href');
+		if($link)
+			{
+			my $file = &resolvePath($file,$link); 
+			if(-e $file)
+				{
+				&combineLink($node,&resolveURI($file,$link));
+				}
+			else
+				{
+				print STDERR "Note: $file not found\n";
+				}
+			return;
+			}
+		}
+	elsif($tag=~/^(SystemDefinition|systemModel)$/ )
+		{
+		}
+	elsif($tag eq 'unit')
+		{
+		foreach my $atr ('bldFile','mrp','base','proFile')
+			{
+			my $link= $node->getAttribute($atr);
+			if($link && !($link=~/^\//))
+				{
+				$link= &abspath(File::Basename::dirname($file)."/$link");
+				foreach my $a (keys %rootmap) {
+					$link=~s,^$a,$rootmap{$a},ie;
+				}
+				# remove leading ./  which is used to indicate that paths should remain relative
+				$link=~s,^\./([^/]),$1,; 
+				$node->setAttribute($atr,$link);
+				}
+			}
+		}
+	elsif($tag eq 'meta')
+		{
+		my $link= $node->getAttribute('href');
+		$link=~s,^file://(/([a-z]:/))?,$2,; # convert file URI to absolute path
+		if ($link ne '' ) 
+			{ 
+			if($link=~/^[\/]+:/)
+				{
+				print STDERR "Note: Remote URL $link not embedded\n";
+				next; # do not alter children
+				}
+			if(! ($link=~/^\//))
+				{
+				$link= &abspath(File::Basename::dirname($file)."/$link");
+				}
+			if(! -e $link) 
+				{
+				print STDERR "Warning: Local metadata file not found: $link\n";
+				next; # do not alter children
+				}
+			# if we're here we can just embed the file
+			# no processing logic is done! It's just embedded blindly
+			my  $metadoc = $parser->parsefile ($file);
+			my $item =&firstElement($metadoc->getDocumentElement);
+			if(!$item)
+				{
+				print STDERR "Warning: Could not process metadata file: $link\n";
+				next; # do not alter children
+				}
+			$node->removeAttribute('href');
+			foreach my $child (@{$item->getChildNodes})
+				{
+				&blindCopyInto($node,$child);
+				next;
+				}
+			}
+		if($node->getAttribute('rel') eq 'link-mapping')
+			{# need to process this now
+			&rootMapMeta($node);
+			}
+		return;
+		}
+	else {return}
+	my $checkversion=0;
+	foreach my $item (@{$node->getChildNodes})
+		{
+		#print $item->getNodeType,"\n";
+		&walk($file,$item);
+		$checkversion = $checkversion  || ($tag eq 'component' &&  $item->getNodeType==1 && $item->getAttribute('version') ne '');
+		}
+
+	if($checkversion && $config ne '')
+		{ # need to check the conf metadata on the units in this component
+		&doCmpConfig($node);
+		}
+	foreach my $item (@{$node->getChildNodes})
+		{
+		if ($item->getNodeType==1 && $item->getTagName eq 'meta')
+			{
+			&processMeta($item);
+			}
+		}
+	}
+
+
+sub combineLink
+	{
+	# combine data from linked sysdef fragment w/ equivalent element in parent document
+	my $node = shift;
+	my $file = shift;
+	my $getfromfile = &localfile($file);
+	$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";
+	&fixIDs($item);
+	my %up = &atts($node);
+	my %down = &atts($item);
+	$up{'id'} eq $down{'id'}  || die "$up{id} differs from $down{id}";
+	$node->removeAttribute('href');
+	foreach my $v (keys %up) {delete $down{$v}}
+	foreach my $v (keys %down)
+		{
+		$node->setAttribute($v,$down{$v})
+		}
+	foreach my $child (@{$item->getChildNodes})
+		{
+		&copyInto($node,$child);
+		}
+	&walk($file,$node);
+	}
+
+
+sub blindCopyInto
+	{
+	# make a deep copy the node (2nd arg) into the element (1st arg)
+	my $parent=shift;
+	my $item = shift;
+	my $doc = $parent->getOwnerDocument;
+	my $type = $item->getNodeType;
+	my $new;
+	if($type==1) 
+		{
+		$new = $doc->createElement($item->getTagName);
+		my %down = &atts($item);
+		while(my($a,$b) = each(%down))
+			{
+			$new->setAttribute($a,$b);
+			}
+		foreach my $child (@{$item->getChildNodes})
+			{
+			&blindCopyInto($new,$child);
+			}
+		}
+	elsif($type==3) 
+		{
+		$new = $doc->createTextNode ($item->getData);
+		}
+	elsif($type==8) 
+		{
+		$new = $doc->createComment  ($item->getData);
+		}
+	if($new)
+		{
+		$parent->appendChild($new);
+		}
+	}
+
+sub copyInto
+	{
+	# make a deep copy the node (2nd arg) into the element (1st arg)
+	my $parent=shift;
+	my $item = shift;
+	my $doc = $parent->getOwnerDocument;
+	my $type = $item->getNodeType;
+	my $new;
+	if($type==1) 
+		{
+		&fixIDs($item);
+		$new = $doc->createElement($item->getTagName);
+		my %down = &atts($item);
+		foreach my $ordered ('id','name','bldFile','mrp','level','levels','introduced','deprecated','filter')
+			{
+			if($down{$ordered})
+				{
+				$new->setAttribute($ordered,$down{$ordered});
+				delete $down{$ordered}
+				}
+			}
+		while(my($a,$b) = each(%down))
+			{
+			$new->setAttribute($a,$b);
+			}
+		foreach my $child (@{$item->getChildNodes})
+			{
+			&copyInto($new,$child);
+			}
+		}
+	elsif($type==3) 
+		{
+		$new = $doc->createTextNode ($item->getData);
+		}
+	elsif($type==8) 
+		{
+		$new = $doc->createComment  ($item->getData);
+		}
+	if($new)
+		{
+		$parent->appendChild($new);
+		}
+	}
+
+sub getNs
+	{
+	# find the namespace URI that applies to the specified prefix.
+	my $node = shift;
+	my $pre = shift;
+	my $uri = $node->getAttribute("xmlns:$pre");
+	if($uri) {return $uri}
+	my $parent = $node->getParentNode;
+	if($parent && $parent->getNodeType==1)
+		{
+		return getNs($parent,$pre);
+		}
+	}
+
+
+sub fixIDs
+	{
+	# translate the ID to use the root doc's namespaces 
+	my $node = shift;
+	foreach my $id ('id','before')
+		{
+		&fixID($node,$id);
+		}
+}
+
+sub fixID
+	{
+	# translate the ID to use the root doc's namespaces 
+	my $node = shift;
+	my $attr = shift || 'id';
+	my $id = $node->getAttribute($attr);
+	if($id eq '') {return}
+	my $ns;
+	if($id=~s/^(.*)://)
+		{ # it's got a ns, find out what it is
+		my $pre = $1;
+		$ns=&getNs($node,$pre);
+		}
+	else
+		{
+		$ns = $node->getOwnerDocument->getDocumentElement->getAttribute("id-namespace") ||
+			$defaultns;
+		}
+	$ns = $urimap{$ns};
+	$id = ($ns eq '') ? $id : "$ns:$id";
+	return $node->setAttribute($attr,$id);
+}
+
+sub firstElement {
+	# return the first element in this node
+	my $node = shift;
+	foreach my $item (@{$node->getChildNodes}) {
+		if($item->getNodeType==1) {return $item}
+	}
+}
+
+
+sub atts {
+	# return a hash of all attribtues defined for this element
+	my $node = shift;
+	my %at = $node->getAttributes;
+	my %list;
+	foreach my $a (keys %{$node->getAttributes}) 
+		{
+		if($a ne '')
+			{
+			$list{$a} = $node->getAttribute ($a);
+			}
+		}
+	return %list;
+}
+
+
+sub ns 
+	{
+	# return a hash of ns prefix and uri -- the xmlns: part is stripped off
+	my $node = shift;
+	my %list;
+	foreach my $a (keys %{$node->getAttributes}) 
+		{
+		my $pre = $a;
+		if($pre=~s/^xmlns://)
+			{
+			$list{$pre} = $node->getAttribute ($a);
+			}
+		}
+	return %list;
+	}
+
+
+sub resolvePath
+	{
+	# return full path to 2nd arg relative to first (path or absolute URI)
+	my $base = shift;
+	my $path = shift;
+	if($path=~m,^/,) {return $path } # path is absolute, but has no drive. Let OS deal with it.
+	if($path=~s,^file:///([a-zA-Z]:/),$1,) {return $path } # file URI with drive letter
+	if($path=~m,^file://,) {return $path } # file URI with no drive letter (unit-style). Just pass on as is with leading / and let OS deal with it
+	if($path=~m,^[a-z0-9][a-z0-9]+:,i) {return $path } # absolute URI -- no idea how to handle, so just return
+	return &abspath(File::Basename::dirname($base)."/$path");
+	}
+
+
+sub resolveURI
+	{
+	# return full path to 2nd arg relative to first (path or absolute URI)
+	my $base = shift;
+	my $path = shift;
+	if($path=~m,[a-z0-9][a-z0-9]+:,i) {return $path } # absolute URI -- just return
+	if($path=~m,^/,) {return $path } # path is absolute, but has no drive. Let OS deal with it.
+	return &abspath(File::Basename::dirname($base)."/$path");
+	}
+
+sub localfile
+	{
+	my $file = shift;
+	if($file=~s,file:///([a-zA-Z]:/),$1,) {return $file } # file URI with drive letter
+	if($file=~m,file://,) {return $file } # file URI with no drive letter (unit-style). Just pass on as is with leading / and let OS deal with it
+	if($file=~m,^([a-z0-9][a-z0-9]+):,i)
+		{
+		print STDERR "ERROR: $1 scheme not supported\n";
+		return;  # return empty string if not supported.
+		} 
+	return $file
+	}
+
+sub namespaces
+	{
+	# return a list of namespace URI / prefix pairs, in the order they're defined
+	# these need to be used to define namespaces in the root element
+	my $file = shift;
+	my $node = shift;
+	my $type = $node->getNodeType;
+	if($type!=1) {return}
+	my $tag = $node->getTagName;
+	my @res;
+	my %nslist = &ns($node);
+	while(my($pre,$uri)=each(%nslist))
+		{ # push all namespaces defined here onto the list
+		push(@res,$uri,$pre);
+		}
+	if($tag=~/^(layer|package|collection|component)$/ )
+		{ # these have the potential of linking, so check for that
+		my $link= $node->getAttribute('href');
+		if($link)
+			{
+			$link=&resolvePath($file,$link);
+			if(-e $link)
+				{
+				my  $doc = $parser->parsefile ($link);
+				my @docns = &namespaces($link,$doc->getDocumentElement);
+				undef $doc;
+				return (@res,@docns);
+				#ignore any children nodes if this is a link
+				}
+			print STDERR "Note: $link not found\n";
+			}
+		}
+	elsif($tag eq 'SystemDefinition' )
+		{
+		my $default = $node->getAttribute('id-namespace');
+		if($default)
+			{# mangle with a space so it's clear it's not a qname
+			push(@res,$default,'id namespace');
+			}
+		}
+	foreach my $item (@{$node->getChildNodes})
+		{
+		push(@res,&namespaces($file,$item));
+		}
+	return @res;
+	}
+
+sub processMeta
+	{ # acts upon any known <meta> and strips it from the output if it's used
+	my $metanode = shift;
+
+	my $rel = $metanode->getAttribute('rel') || 'Generic';
+	if($rel eq 'config' && $config ne '')
+		{ # only process if there is something to configure
+		&doconfig($metanode);
+		}
+	else 
+		{
+		# do nothing. Not supported yet
+		}
+	}
+
+sub doCmpConfig
+	{ # configure in or out the units in a component
+	my $cmp = shift;	# the component node
+	my @unversioned;	# list of all units with no version attribute (if more than one, they should all have filters defined)
+	my %versioned;		# hash table of all units with a specified version, it's a fatal error to hav the same verison twice in one component
+	foreach my $item (@{$cmp->getChildNodes})
+		{ # populate %versioned and @unversioned to save processsing later
+		if($item->getNodeType==1 && $item->getTagName eq 'unit')
+			{
+			my $ver = $item->getAttribute('version');
+			if($ver eq '') {push(@unversioned,$item)}
+			else
+				{
+				defined $versioned{$ver}  && die "Cannot have more than one unit with version $ver in the same component ".$cmp->getAttribute('id');
+				$versioned{$ver}=$item;
+				}
+			}
+		}
+	my @picks = &getMetaConfigPick($cmp); # the list, in order, of all <pick> elements that affect this component
+	foreach my $pick (@picks)
+		{
+		my $ver = $pick->getAttribute('version');
+		if(!$versioned{$ver})
+			{
+			print STDERR "ERROR: Reference to invalid unit version $ver in component ",$cmp->getAttribute('id'),". Ignoring.\n";
+			return;
+			}
+		if(&definedMatches($pick))
+			{ # remove all other units;
+			delete $versioned{$ver}; # to avoid removing in loop
+			foreach my $unit (@unversioned, values(%versioned))
+				{
+				$cmp->removeChild($unit);
+				print STDERR "Note: unit ",$unit->getAttribute('version')," in component " ,$cmp->getAttribute('id')," configured out\n";
+				}
+			last; # done. No more processing after first match
+			}
+		else
+			{ # remove this unit and continue
+			$cmp->removeChild($versioned{$ver});
+			print STDERR "Note: unit $ver in component " ,$cmp->getAttribute('id')," configured out\n";
+			delete $versioned{$ver}; # gone, don't process anymore;
+			}
+		}
+	if (scalar(@unversioned, values(%versioned)) > 1)
+		{
+		print STDERR "Warning: component ",$cmp->getAttribute('id')," has more than one unit after configuration\n";
+		}
+	}
+
+	
+sub getMetaConfigPick
+	{	# return an array of all <pick> elements that affect the specified element
+	my $node = shift;
+	my @pick;
+	while($node->getParentNode->getNodeType==1)
+		{
+		foreach my $item (@{$node->getChildNodes})
+			{
+			my @picks;
+			if($item->getNodeType==1 &&  $item->getAttribute('rel') eq 'config') 
+				{ # it's conf metadata
+				foreach my $p (@{$item->getChildNodes})
+					{
+					if($p->getNodeType==1 &&  $p->getTagName eq 'pick') {push(@picks,$p)}
+					}
+				}
+			@pick=(@picks,@pick); # prepend this to the start;
+			}
+		$node=$node->getParentNode;
+		}
+	return @pick;
+	}
+
+sub definedMatches
+	{ # process all <defined> and <not-defined> the specified element and return true or false if the combination matches
+	my $node  = shift;
+	my $match = 1;
+	foreach my $def (@{$node->getChildNodes})
+		{
+		if($def->getNodeType == 1) 
+			{
+			my $tag = $def->getTagName;
+			if($tag eq 'defined' or $tag eq 'not-defined')
+				{
+				my $var = $def->getAttribute('condition') || die "Must have condition set on all $tag elements";
+				$defineParams{$var} && die "Cannot use a macro with parameters as a feature flag: $var(".$defineParams{$var}->[0].")"; 
+				$match = $match &&  (($tag eq 'defined') ? defined($defines{$var}) : ! defined($defines{$var}));
+				}
+			}
+		}
+		return $match;
+	}
+
+sub doconfig
+	{ # confgure in or out a system model item that owns the specified <meta>, remove the <meta> when done.
+	my $meta  = shift;
+	my $keep = definedMatches($meta);
+	my $parent = $meta->getParentNode;
+	if(!$keep)
+		{
+		print STDERR "Note: ",$parent->getTagName," " ,$parent->getAttribute('id')," configured out\n";
+		$parent->getParentNode->removeChild($parent);
+		return; # it's removed, so there's nothing else we can possibly do
+		}
+
+	$parent->removeChild($meta);
+	}
+
+sub getDefines
+	{ # populate the list of #defines from a specified .hrh file.
+	my $file = shift;
+	my $inc;
+	foreach my $i (@includes)
+		{
+		$inc.=" -I$i";
+		}
+	open(CPP,"cpp -dD$inc \"$file\"|");
+	while(<CPP>)
+		{
+		if(!/\S/){next} # skip blank lines
+		if(/^# [0-9]+ /) {next} # don't care about these
+		s/\s+$//;
+		if(s/^#define\s+(\S+)\((.*?)\)\s+//)
+			{ #parametered define
+			push(@{$defineParams{$1}},@2,$_);
+			}
+		elsif(s/^#define\s+(\S+)//)
+			{ # normal define
+			my $def = $1;
+			s/^\s+//;
+			$defines{$1}=$_;
+			}
+		else {die "cannot process $_";}
+		}
+	close CPP;
+	}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysdeftools/joinsysdef.xsl	Tue Apr 06 10:25:29 2010 +0100
@@ -0,0 +1,38 @@
+<?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:
+	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 -->
+
+<xsl:param name="path">/os/deviceplatformrelease/foundation_system/system_model/system_definition.xml</xsl:param>
+
+<xsl:template match="/*">
+	<xsl:apply-templates select="." mode="join"/>
+</xsl:template>
+
+
+<xsl:template match="/SystemDefinition[systemModel]">
+<xsl:apply-templates select="." mode="join">
+	<xsl:with-param name="filename" select="$path"/>
+</xsl:apply-templates>
+</xsl:template>
+
+
+<xsl:template match="meta[@rel='Api']" priority="2" mode="meta"/> <!-- ignore these, not needed in system build -->
+
+
+<xsl:include href="joinsysdef-module.xsl"/>
+
+</xsl:stylesheet>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysdeftools/mergesysdef-module.xsl	Tue Apr 06 10:25:29 2010 +0100
@@ -0,0 +1,504 @@
+<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
+	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 for merging only two sysdef files according to the 3.0.0 rules. Old syntax not supported and must be converetd before calling.
+-->
+	
+<xsl:variable name="defaultnamespace">http://www.symbian.org/system-definition</xsl:variable>
+
+<xsl:template match="/SystemDefinition[starts-with(@schema,'2.') or starts-with(@schema,'1.')]" priority="2" mode="merge-models">
+	<xsl:message terminate="yes">ERROR: Syntax <xsl:value-of select="@schema"/> not supported</xsl:message>
+</xsl:template>
+<xsl:template match="/SystemDefinition[not(systemModel)]" priority="2" mode="merge-models">
+	<xsl:message terminate="yes">ERROR: Can only merge stand-alone system models</xsl:message>
+</xsl:template>
+
+<!-- stuff for dealing with namespaces -->
+
+
+<xsl:template match="node()|@*" mode="translate-namespaces"><xsl:copy-of select="."/></xsl:template>
+<!-- don't translate meta or unit tags, just copy verbatim -->
+<xsl:template match="meta|unit" mode="translate-namespaces" priority="2">
+<xsl:element name="{name()}">
+<xsl:copy-of select="@*|*|comment()"/>
+</xsl:element>
+</xsl:template>
+
+<xsl:template match="*" mode="translate-namespaces"><xsl:param name="nsdoc"/>
+<xsl:element name="{name()}">
+<xsl:apply-templates select="@*|node()" mode="translate-namespaces">
+	<xsl:with-param name="nsdoc" select="$nsdoc"/>
+</xsl:apply-templates>
+</xsl:element>
+</xsl:template>
+
+
+<xsl:template match="@id|@before" mode="translate-namespaces"><xsl:param name="nsdoc"/>
+	<xsl:attribute name="{name()}">
+		<xsl:variable name="id">
+			<xsl:choose>
+				<xsl:when test="contains(.,':')">
+					<xsl:value-of select="substring-after(.,':')"/>
+				</xsl:when>
+				<xsl:otherwise>
+					<xsl:value-of select="."/>
+				</xsl:otherwise>
+			</xsl:choose>
+		</xsl:variable>
+		<xsl:variable name="ns">
+			<xsl:choose>
+				<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>
+				<xsl:otherwise>
+					<xsl:value-of select="$defaultnamespace"/>
+				</xsl:otherwise>
+			</xsl:choose>
+		</xsl:variable>
+		<xsl:choose>
+			<xsl:when test="not($nsdoc/@id-namespace) and $defaultnamespace=$ns">
+				<xsl:value-of select="$id"/>
+			</xsl:when>
+			<xsl:when test="$nsdoc/@id-namespace=$ns">
+				<xsl:value-of select="$id"/>
+			</xsl:when>
+			<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:variable name="myns">
+					<xsl:apply-templates mode="ns-prefix" select="$nsdoc">
+						<xsl:with-param name="ns" select="$ns"/>
+					</xsl:apply-templates>
+				</xsl:variable>			
+				<xsl:value-of select="concat($myns,':',$id)"/>
+			</xsl:when>
+			<xsl:otherwise> <!-- some namespace that needed to be defined --> 
+			<xsl:message>Warning: need definition for namespace "<xsl:value-of select="$ns"/>" for <xsl:value-of select="$id"/></xsl:message>
+				<xsl:value-of select="."/>					
+			</xsl:otherwise>
+		</xsl:choose>		
+	</xsl:attribute>
+</xsl:template>
+
+<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 -->
+	<xsl:param name="chars">ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz</xsl:param> <!-- single letter namespace prefixes to try -->
+	<xsl:variable name="name" select="substring(substring-after($ns,'http://www.'),1,1)"/>
+	<xsl:choose>
+		<xsl:when test="$pre!='' and $pre!='id-namespace' and not(//namespace::*[name()=$pre]) and not(contains($dontuse,concat(' ',$pre,' ')))">
+			<xsl:value-of select="$pre"/>
+		</xsl:when>
+		<xsl:when test="$ns='' and $chars=''">
+			<xsl:message terminate="yes">ERROR: Cannot create namespace prefix for downstream default namespace in <xsl:value-of select="*/@id"/></xsl:message>
+		</xsl:when>
+		<xsl:when test="$name!='' and not(contains($dontuse,concat(' ',$name,' ')))"><xsl:value-of select="$name"/></xsl:when>
+		<xsl:when test="namespace::*[name()=substring($chars,1,1)] or contains($dontuse,concat(' ',substring($chars,1,1),' '))">
+			<xsl:apply-templates mode="ns-prefix">
+				<xsl:with-param name="chars" select="substring($chars,2)"/>
+			</xsl:apply-templates>
+		</xsl:when>
+		<xsl:otherwise>
+			<xsl:value-of select="substring($chars,1,1)"/>
+		</xsl:otherwise>
+	</xsl:choose>
+</xsl:template>
+
+
+<!--  need to make sure this handles <meta> correctly -->
+
+<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. -->
+	
+	<!-- do some testing -->
+ 	<xsl:if test="$other[starts-with(@schema,'2.') or starts-with(@schema,'1.')]">
+		<xsl:message terminate="yes">ERROR: Syntax <xsl:value-of select="$other/@schema"/> not supported</xsl:message>
+	</xsl:if>
+	<xsl:if test="not($other/systemModel)">
+		<xsl:message terminate="yes">ERROR: Can only merge stand-alone system models</xsl:message>
+	</xsl:if>
+	 
+	<xsl:copy>
+		<xsl:copy-of  select="@*"/> <!--  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 -->
+				
+				<xsl:copy-of select="namespace::*[name()!='xml']"/> <!-- all upstream namespaces -->
+
+				<xsl:variable name="cur" select="."/>
+				<xsl:for-each select="$other/namespace::*"> <!-- all namespaces in downstream not already in upstream -->
+					<xsl:if test="not((. = $cur/@id-namespace) or (not($cur/@id-namespace) and .= $defaultnamespace) or  $cur/namespace::*[.=current()])">
+							<!-- namespace in downstream not in upstream doc -->
+							<xsl:variable name="newprefix">
+								 <!-- test to see if the ns prefix already exists -->
+								<xsl:apply-templates select="$cur" mode="ns-prefix">
+									<xsl:with-param name="ns" select="."/>
+									<xsl:with-param name="pre" select="name()"/>
+								</xsl:apply-templates>
+							</xsl:variable>
+							<xsl:copy/>
+					</xsl:if>   
+				</xsl:for-each>
+				
+					<xsl:if test="not(($other/@id-namespace = @id-namespace) or (not($other/@id-namespace) and not(@id-namespace)) or (not(@id-namespace) and $other/@id-namespace = $defaultnamespace) or namespace::*[.=$other/@id-namespace])">  
+						<!-- default namespace in downstream not in upstream doc -->
+						<!-- need to make created ns a bit more intelligent -->
+						<xsl:attribute name="bar" namespace="{$other/@id-namespace}">
+							<xsl:value-of select="$other/@id-namespace"/>
+						</xsl:attribute>
+				</xsl:if>
+			</xsl:copy>
+		</xsl:variable>
+
+		
+		<!-- copy the namespaces to currently open element (the root one) -->
+		<xsl:copy-of select="namespace::*"/>
+		<xsl:for-each select="$other/namespace::*[.!=current()/namespace::*]"><xsl:copy/></xsl:for-each>
+		<xsl:for-each select="exslt:node-set($namespaces)/*/namespace::*"><xsl:copy/></xsl:for-each>
+	<!-- translate all IDs in downstream doc to use namespaces from upstream doc  
+		This is so much easier than having to propigate this info around while creating the doc-->
+	<xsl:variable name="otherdoc">
+		<xsl:apply-templates mode="translate-namespaces" select="$other">
+			<xsl:with-param name="nsdoc" select="exslt:node-set($namespaces)/* | ."/>
+		</xsl:apply-templates>
+	</xsl:variable>
+		<xsl:apply-templates mode="merge-models">
+			<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:apply-templates>
+	
+	</xsl:copy>
+</xsl:template>
+
+<xsl:template match="systemModel" mode="merge-models">
+	<xsl:param name="other"/>	<!-- the parent of the downstream systemModel this is merged with -->
+	<xsl:param name="up"/>
+	<xsl:param name="down"/>
+	<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]"/>	
+		<xsl:apply-templates mode="merge-models">
+			<xsl:with-param name="other" select="$other/systemModel"/>
+			<xsl:with-param name="up" select="$up"/>
+			<xsl:with-param name="down" select="$down"/>
+		</xsl:apply-templates>
+	</xsl:copy>
+</xsl:template>
+
+<xsl:template match="@*|*|comment()" mode="merge-models"><xsl:copy-of select="."/></xsl:template>
+
+
+<xsl:template match="meta|comment()[following-sibling::meta]" mode="merge-models"/>
+	<!-- copy elesewhere, not here so that metas always appear first-->
+
+
+
+<!-- merge levels attribute via std rules -->
+<xsl:template match="layer/@levels|package/@levels" mode="merge-models">
+	<xsl:param name="other"/><!-- the element contains the other @levels -->
+	<xsl:choose>
+		<!--  if they are the same, or not specified in the other,  just copy -->
+		<xsl:when test=".=$other/@levels or not($other/@levels)"><xsl:copy-of select="."/></xsl:when>
+		<xsl:when test="contains(concat(' ',normalize-space(.),' '),concat(' ',normalize-space($other/@levels),' '))">
+			<!--upstream completely contains downstream, just copy --> 
+			<xsl:copy-of select="."/>
+		</xsl:when>
+		<xsl:when test="contains(concat(' ',normalize-space($other/@levels),' '),concat(' ',normalize-space(.),' '))">
+			<!--  If this is contained is other, then use other-->
+			<xsl:copy-of select="$other/@levels"/>
+		</xsl:when>
+		<xsl:when test="contains(concat(' ',normalize-space($other/@levels),' '),' - ')">
+			<!-- if other uses + syntax, then pre/append -->
+			<xsl:variable name="lev">
+				<xsl:value-of select="substring-before(concat(' ',normalize-space($other/@levels),' '),' - ')"/>
+				<xsl:value-of select="concat(' ',.,' ')"/>
+				<xsl:value-of select="substring-after(concat(' ',normalize-space($other/@levels),' '),' - ')"/>
+			</xsl:variable>
+			<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:copy-of select="."/>
+		</xsl:otherwise>
+	</xsl:choose>
+</xsl:template>
+
+<xsl:template name="copy-sorted-content">
+	<xsl:param name="base"/>
+	<xsl:param name="to-sort"/>
+	<xsl:param name="start"/>
+	<xsl:param name="end"/>
+	<xsl:param name="down"/>
+	<xsl:param name="remainder" select="/.."/>
+
+	<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:choose>
+</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: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: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="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: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:apply-templates>
+
+	
+	<xsl:copy>
+		<xsl:apply-templates select="@*" mode="merge-models"> <!-- copy upstream attributes -->
+			<xsl:with-param name="other" select="$match"/>
+		</xsl:apply-templates>
+		
+		<xsl:if test="self::component and not(@origin-model) and $up/@name">
+			<!-- insert origin-model and optional root for components only -->
+			<xsl:attribute name="origin-model">
+				<xsl:value-of select="$up/@name"/>
+			</xsl:attribute>
+			<xsl:if test="not(@root)">
+				<xsl:copy-of select="$up/@root"/>
+			</xsl:if>
+		</xsl:if>
+		
+		<xsl:for-each select="$match/@*">  <!-- 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:choose>
+			<xsl:when test="self::component">
+				<!-- copy all units, metas and comments from this
+					copy all metas in the merged component
+					copy any new comments in the merged component (not duplicates)
+					if there are no units in the this, copy all units in the merged component
+					if there are units in this, copy only the versioned units in the merged component (only those versions not already specified) -->
+				<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()]"/>				
+			</xsl:when>
+			<xsl:otherwise>
+
+				<!--  copy metas and comments in between meta. Do not try to merge metadata between models -->
+				<xsl:copy-of select="meta | $match/meta | comment()[following-sibling::meta]"/>
+				
+				<xsl:apply-templates mode="merge-models">
+					<xsl:with-param name="other" select="$match"/>
+					<xsl:with-param name="up" select="$up"/>
+					<xsl:with-param name="down" select="$down"/>
+				</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: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:template>
+
+
+
+<xsl:template match="*" 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="not(self::layer) and count($root/descendant::*[name()=name(current()/..) and @id!=current()/../@id]/*[@id=current()/@id])">
+			<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>
+		</xsl:when>
+		<xsl:otherwise>
+			<!-- save all content in a variable to test to see if it's got any problems (ie been removed due to errors)-->
+			<xsl:variable name="content">
+				<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:variable>
+			<xsl:choose>
+				<!-- if all elements in this have been deleted, throw out this element -->
+				<xsl:when test="not(exslt:node-set($content)/*) and *">
+					<xsl:message>Warning: All content in downstream <xsl:value-of select="name()"/> "<xsl:value-of select="@id"/>" is invalid. Ignoring <xsl:value-of select="name()"/>
+						<xsl:text>&#xa;</xsl:text>
+					</xsl:message>
+				</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:copy-of select="exslt:node-set($content)"/>
+					</xsl:copy>
+				</xsl:otherwise>
+			</xsl:choose>					
+		</xsl:otherwise>
+	</xsl:choose>
+</xsl:template>
+
+
+<xsl:template match="comment()|@*" mode="merge-copy-of">
+	<xsl:copy-of select="."/>
+</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]">
+			<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>
+		</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:if test="not(@origin-model) and $origin/@name">
+					<xsl:attribute name="origin-model">
+						<xsl:value-of select="$origin/@name"/>
+					</xsl:attribute>
+					<xsl:if test="not(@root)">
+						<xsl:copy-of select="$origin/@root"/>
+					</xsl:if>
+				</xsl:if>
+				<xsl:copy-of select="*|comment()"/>
+			</xsl:copy>
+		</xsl:otherwise>
+	</xsl:choose>
+</xsl:template>
+
+</xsl:stylesheet>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysdeftools/mergesysdef.xsl	Tue Apr 06 10:25:29 2010 +0100
@@ -0,0 +1,100 @@
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:exslt="http://exslt.org/common">
+<!--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:
+	Merge two 3.x syntax system definitions
+-->
+
+	<xsl:output method="xml" indent="yes"/>
+	<xsl:param name="Downstream">mcl/System_Definition_Template.xml</xsl:param>
+	<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>
+		<xsl:when test="$downstream[starts-with(@schema,'2.') or starts-with(@schema,'1.')  or not(systemModel)]">
+			<xsl:message terminate="yes">Syntax <xsl:value-of select="@schema"/> not supported</xsl:message>
+		</xsl:when>
+		<xsl:when test="/SystemDefinition/systemModel/@name=$downstream/systemModel/@name">
+			<xsl:apply-templates mode="origin-term" select="/*">
+				<xsl:with-param name="root">Upstream</xsl:with-param>
+			</xsl:apply-templates>
+			</xsl:when>
+		<xsl:otherwise><xsl:value-of select="/SystemDefinition/systemModel/@name"/></xsl:otherwise>
+	</xsl:choose>
+</xsl:param>
+
+<xsl:param name="downname">
+	<xsl:choose>
+		<xsl:when test="/SystemDefinition/systemModel/@name=$downstream/systemModel/@name">
+			<xsl:apply-templates mode="origin-term" select="$downstream">	
+				<xsl:with-param name="root">Downstream</xsl:with-param>
+			</xsl:apply-templates>
+			</xsl:when>
+		<xsl:otherwise><xsl:value-of select="$downstream/systemModel/@name"/></xsl:otherwise>
+	</xsl:choose>
+</xsl:param>
+
+<xsl:template mode="origin-term" match="*">
+	<xsl:param name="root"/>
+	<xsl:param name="index"/>
+	<xsl:choose>
+		<xsl:when test="not(key('origin',concat($root,$index)))">
+			<xsl:value-of select="concat($root,$index)"/>
+		</xsl:when>
+		<xsl:when test="$index=''">
+			<xsl:apply-templates mode="origin-term" select=".">	
+				<xsl:with-param name="root" select="$root"/>
+				<xsl:with-param name="index" select="1"/>
+			</xsl:apply-templates>
+		</xsl:when>
+		<xsl:otherwise>
+			<xsl:apply-templates mode="origin-term" select=".">	
+				<xsl:with-param name="root" select="$root"/>
+				<xsl:with-param name="index" select="$index + 1"/>
+			</xsl:apply-templates>		
+		</xsl:otherwise>
+	</xsl:choose>
+</xsl:template>
+
+
+<!--  this merge only two files according to the 3.0.0 rules. Old syntax not supported. Must be converetd before calling -->
+
+
+
+<xsl:template match="/*">
+	<xsl:variable name="upmodel">
+		<sysdef name="{$upname}"/>
+	</xsl:variable>
+	<xsl:variable name="downmodel">
+		<sysdef name="{$downname}"/>
+	</xsl:variable>
+	
+	<xsl:choose>
+		<xsl:when test="function-available('exslt:node-set')">
+			<xsl:apply-templates mode="merge-models" select=".">
+				<xsl:with-param name="other" select="$downstream"/>
+				<xsl:with-param name="up" select="exslt:node-set($upmodel)/sysdef"/>
+				<xsl:with-param name="down" select="exslt:node-set($downmodel)/sysdef"/>
+			</xsl:apply-templates>
+		</xsl:when>
+		<xsl:otherwise> <!-- no node set funcion, so don't bother setting the names -->
+			<xsl:apply-templates mode="merge-models" select=".">
+				<xsl:with-param name="other" select="$downstream"/>
+			</xsl:apply-templates> 		
+		</xsl:otherwise>
+	</xsl:choose>
+</xsl:template>
+
+<xsl:include href="mergesysdef-module.xsl"/>
+</xsl:stylesheet>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysdeftools/readme.txt	Tue Apr 06 10:25:29 2010 +0100
@@ -0,0 +1,21 @@
+Filtering tools: 
+filtering.xsl - Filter a sysdef in the 2.0 or 3.0 syntax
+	filter-module.xsl - XSLT module which contains the logic to process the filter attribute in the system definition
+
+Joining tools: 
+joinsysdef.pl - Create a stand-alone sysdef from a linked set of fragments. Supports confguring via an .hrh file.
+joinsysdef.xsl - Create a stand-alone sysdef from a linked set of fragments
+joinandparesysdef.xsl - Create a stand-alone sysdef from a linked set of fragments, paring down to just a set of items of the desired rank.
+	joinsysdef-module.xsl - XSLT module which contains the logic to join a system definition file
+
+Merging tools: 
+mergesysdef.xsl - Merge two 3.x syntax stand-alone system definitions
+	mergesysdef-module.xsl - XSLT module for merging only two sysdef files according to the 3.0.0 rules
+
+Other Tools:
+sysdefdowngrade.xsl - Convert a 3.0.0 sysdef to 2.0.1 sytnax
+
+XSLT Processing:
+xalan.jar
+xercesImpl.jar
+xml-apis.jar
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysdeftools/rootsysdef.pl	Tue Apr 06 10:25:29 2010 +0100
@@ -0,0 +1,744 @@
+use strict;
+
+
+use FindBin;		# for FindBin::Bin
+use lib $FindBin::Bin;
+use lib "$FindBin::Bin/lib";
+
+use Cwd;
+use Cwd 'abs_path';
+use Getopt::Long;
+use File::Basename;
+use File::Spec;
+use XML::DOM;
+
+my $output;
+my $path;
+my $defaultns = 'http://www.symbian.org/system-definition';	# needed if no DTD
+my @searchpaths;
+my @searchroots;
+my %additional;
+my %add;
+my %newNs;
+my $warning = "Error";
+my $placeholders=0;
+
+my @tdOrder =("hb","se", "lo","dc", "vc" , "pr", "dm", "de", "mm", "ma" , "ui",  "rt", "to" );
+
+# need to add options for controlling which metas are filtered out and which are included inline
+GetOptions
+	(
+	 'path=s' => \$path,
+	'output=s' => \$output,
+	'w=s' => \$warning,
+	'root=s' => \@searchroots,
+	'glob=s' => \@searchpaths,
+	'placeholders=s' => \$placeholders
+	);
+
+
+ if($path eq '') {$path = '/os/deviceplatformrelease/foundation_system/system_model/system_definition.xml'}
+
+if(!($warning =~/^(Note|Warning|Error)$/)) {$warning="Error"}
+
+# path is the system model path of the processed sysdef file. This is only used when creating a stand-alone sysdef as the output
+# output specifies the file this is saved in. If specified, all (relative) paths will be modified to be relative to it. If not, all paths will be absolute
+# w is the warning level: Note, Warning or Error.
+# root = -root g:\sf
+# glob = -glob "\*\*\package_definition.xml"
+
+#rootsysdef.pl -root F:\dev\personal\sftest\sf\mcl  -glob "\*\*\package_definition.xml"  -output ..\..\..\deviceplatformrelease\nokia_system\system_definition.sf.xml  ..\..\..\deviceplatformrelease\foundation_system\system_model\system_definition.xml
+
+my %replacefile;
+my $dir;
+foreach(@searchpaths)
+	{
+	my $ndir = shift(@searchroots);
+	if($ndir ne '') {$dir=$ndir}
+	foreach my $file (glob "$dir$_")
+		{
+		my $map =substr($file,length($dir));
+		$map=~tr/\\/\//;
+		$additional{$map}=$file;
+		$replacefile{&abspath($file)}=$map;
+		$add{&abspath($file)}=1;
+		}
+	}
+
+my $sysdef = &abspath(shift);	# resolve the location of the root sysdef
+
+# rootmap is a mapping from the filesystem to the paths in the doc
+my %rootmap = &rootMap($path,$sysdef);	
+my %nsmap;
+my %urimap;
+
+
+
+my $parser = new XML::DOM::Parser;
+my   $sysdefdoc = $parser->parsefile ($sysdef);
+
+my $mapmeta;
+my $modpath;
+if($output eq '')
+	{ #figure out mapping path
+	my @fspath = split(/[\\\/]/,$sysdef);
+	my @smpath = split(/[\\\/]/,$path);
+	while(lc($smpath[$#smpath]) eq lc($fspath[$#fspath] )) {
+		pop(@smpath);
+		pop(@fspath);
+	}
+	my $mappath = join('/',@fspath);
+	my $topath = join('/',@smpath);
+	$mappath=~s,^/?,file:///,;
+	$mapmeta = $sysdefdoc->createElement('meta');
+	$mapmeta->setAttribute('rel','link-mapping');
+	my $node = $sysdefdoc->createElement('map-prefix');
+	$node->setAttribute('link',$mappath);
+	$topath ne '' && $node->setAttribute('to',$topath);
+	$mapmeta->appendChild($node);
+	}
+else
+	{
+	$modpath = &relativeTo(&abspath($output), $sysdef);
+	}
+
+
+# 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 
+#	maybe skipping the contends of <meta>
+my @nslist = &namespaces($sysdef,$sysdefdoc->getDocumentElement());
+
+my %replacing;
+my %newContainer;
+my %foundDescendants;
+
+foreach(keys %add)
+	{
+	my   $fragment = $parser->parsefile ($_);
+	my $fdoc = $fragment->getDocumentElement();
+	my $topmost =&firstElement($fdoc);
+	my $type = $topmost->getTagName;
+	my $id = $topmost->getAttribute('id');
+	my ($localid,$ns) = &idns($topmost,$id);	
+	my @path = &guessIdInPath($localid,$_);
+	if($type eq 'layer') {@path=@path[0]}
+	elsif($type eq 'package')  {@path=@path[0..1]}
+	elsif($type eq 'collection')  {@path=@path[0..2]}
+	elsif($type eq 'component')  {@path=@path[0..3]}
+	@path = reverse(@path);
+	$add{$_}=join('/',@path)." $localid $ns";
+	$replacing{$type}->{"$localid $ns"} = $_;
+	# keys with a space are namespaced and fully identified, and contain the filename as the content.
+	# keys with no space have unknown namespace and contain a hash of the content
+	$newContainer{join('/',@path[0..$#path-1])}->{"$localid $ns"} = $_;
+	for(my $i=-1;$i<$#path-1;$i++)
+		{
+		$foundDescendants{$path[$i+1]}=1;
+		$newContainer{join('/',@path[0..$i])}->{$path[$i+1]}=1;
+		}
+	}
+
+
+while(@nslist)
+	{
+	my $uri = shift(@nslist);
+	my $prefix =shift(@nslist);
+	if($prefix eq 'id namespace'){$prefix=''}
+	if(defined $urimap{$uri}) {next} # already done this uri
+	$urimap{$uri} = $prefix;
+	if($nsmap{$prefix})
+		{ # need a new prefix for this, guess from the URI (for readability)
+		if($uri=~/http:\/\/(www\.)?([^.\/]+)\./) {$prefix = $2}
+		my $i=0;
+		while($nsmap{$prefix})
+			{ # still no prefix, just make up 
+			$prefix="ns$i";
+			$i++;
+			# next line not really necessary, but it's a good safety to stop infinite loops
+			$i eq 1000 && die "ERROR: cannot create namespace prefix for $uri";
+			}
+		}
+	$nsmap{$prefix}=$uri;
+	}
+
+my $docroot =  $sysdefdoc->getDocumentElement;
+
+my $ns = $docroot->getAttribute('id-namespace');
+if(!$ns && $nsmap{''})
+	{
+	$docroot->setAttribute('id-namespace',$nsmap{''});
+	}
+while(my($pre,$uri) = each(%nsmap))
+	{
+	$pre ne '' || next ;
+	$docroot->setAttribute("xmlns:$pre",$uri);
+	}
+
+&walk($sysdef,$docroot);
+
+if($output eq '') 
+	{
+	print $sysdefdoc->toString;
+	}
+else
+	{
+	$sysdefdoc->printToFile($output);
+	}
+
+ 
+sub abspath
+	{
+	# normalize the path into an absolute one
+	my  ($name,$path) = fileparse($_[0]);
+	if($path eq '' && $name eq '') {return};
+	$path=~tr,\\,/,;
+	if( -e $path)
+		{
+		return abs_path($path)."/$name";
+		}
+	my @dir = split('/',$_[0]);
+	my @new;
+	foreach my $d (@dir)
+		{
+		if($d eq '.') {next}
+		if($d eq '..')
+			{
+			pop(@new);
+			next;
+			}
+		push(@new,$d)
+		}
+	return join('/',@new);
+	}
+
+
+ 
+sub normpath
+	{
+	# normalize the path 
+	my @norm;
+	foreach my $dir(split(/[\\\/]/,shift)) {
+		if($dir eq '.') {next}
+		if($dir eq '..')
+			{
+			if($#norm == -1 || $norm[$#norm] eq '..')
+				{ # keep  as is
+				push(@norm,$dir);
+				}
+			elsif($#norm == 0 && $norm[0] eq '')
+				{  # path begins with /, interpret /.. as just / -- ie toss out
+				next
+				}
+			else
+				{
+				pop(@norm);
+				}
+			}
+		else
+			{
+			push(@norm,$dir);
+			}
+	}
+
+	return join('/',@norm)
+	}
+
+
+sub rootMap {
+	my @pathdirs = split(/\//,$_[0]);
+	my @rootdirs = split(/\//,$_[1]);
+
+	while(lc($rootdirs[$#rootdirs])  eq lc($pathdirs[$#pathdirs])  )
+		{
+		pop(@rootdirs);
+		pop(@pathdirs);
+		}
+	return (join('/',@rootdirs)  => join('/',@pathdirs) );
+	}
+
+sub replacedBy
+	{ # can only check once. Destroys data
+	my $node = shift;
+	my $fullid= join(' ',&idns($node));
+	my $type =  $node->getTagName;
+	my $repl = $replacing{$type}->{$fullid};
+	delete $replacing{$type}->{$fullid};
+	return $repl;
+	}
+
+sub walk
+	{
+	#' walk through the doc, resolving all links
+	my $file = shift;
+	my $node = shift;
+	my $type = $node->getNodeType;
+	if($type!=1) {return}
+	my $tag = $node->getTagName;
+	if($tag=~/^(layer|package|collection|component)$/ )
+		{
+		if($file eq $sysdef)
+			{
+			&fixIDs($node);	# normalise all IDs in the root doc.
+			}
+		my $override = &replacedBy($node);
+		my $link= $node->getAttribute('href');
+		if($override eq '' )
+			{
+			my ($id,$ns)=&idns($node);
+			if($foundDescendants{$id})
+				{ # keep this node, it'll be populated by what we found
+				if($link)
+					{
+					$node->removeAttribute('href');
+					}
+				}
+			elsif($link || !$placeholders)
+				{ # not going to be used, remove
+				$node->getParentNode->removeChild($node) ; # not present, remove
+				return;
+				}
+			}
+		else
+			{	
+			my $href = $node->getAttribute('href');	
+			my $ppath =  join('/',&parentPath($node->getParentNode));
+			delete $newContainer{$ppath}->{join(' ',&idns($node))};		# remove this from list of things which need to be added
+			if(&resolvePath($file,$href) ne $override)
+				{ # file has changed, update
+				print STDERR "$warning: Replacing $tag ",$node->getAttribute('id')," with $override\n";
+				&setHref($node,$override);
+				return;
+				}
+			}
+		my @curpath = &parentPath($node);
+		my $curitem = $curpath[$#curpath];
+		my $curp = join('/',@curpath[0..$#curpath-1]);
+		delete $newContainer{$curp}->{$curitem};
+
+		if($link)
+			{
+			foreach my $child (@{$node->getChildNodes}) {$node->removeChild($child)} # can't have children
+			&fixHref($node,$file);
+			return;
+			}
+		}
+	elsif($tag eq 'systemModel' && $mapmeta)
+		{ # need absolute paths for all links
+		$node->insertBefore ($mapmeta,$node->getFirstChild);
+		}
+	elsif($tag=~/^(SystemDefinition|systemModel)$/ )
+		{
+		}
+	elsif($tag eq 'unit')
+		{
+		foreach my $atr ('bldFile','mrp','base','proFile')
+			{
+			my $link= $node->getAttribute($atr);
+			if($link && !($link=~/^\//))
+				{
+				if($mapmeta)
+					{ # use absolute paths
+					$link= &abspath(File::Basename::dirname($file)."/$link");
+					foreach my $a (keys %rootmap)
+						{
+						$link=~s,^$a,$rootmap{$a},ie;
+						}
+					}
+				else
+					{ # modified relative path 
+					$link = &normpath($modpath.$link);
+					}
+				$node->setAttribute($atr,$link);
+				}
+			}
+		}
+	elsif($tag eq 'meta')
+		{
+		&fixHref($node,$file);
+		&processMeta($node);
+		next;
+		}
+	else {return}
+	foreach my $item (@{$node->getChildNodes})
+		{
+		#print $item->getNodeType,"\n";
+		&walk($file,$item);
+		}
+	if($tag=~/^(systemModel|layer|package|collection|component)$/ )
+		{ # check for appending
+		my $ppath =  join('/',&parentPath($node));
+		if($newContainer{$ppath}) {
+			foreach my $item (sort keys %{$newContainer{$ppath}})
+				{
+				&appendNewItem($node,$item,$newContainer{$ppath}->{$item});
+				}
+			}
+		}
+	}
+
+
+sub getNs
+	{
+	# find the ns URI that applies to the specified prefix.
+	my $node = shift;
+	my $pre = shift;
+	my $uri = $node->getAttribute("xmlns:$pre");
+	if($uri) {return $uri}
+	my $parent = $node->getParentNode;
+	if($parent && $parent->getNodeType==1)
+		{
+		return getNs($parent,$pre);
+		}
+	}
+
+
+sub fixIDs
+	{
+	# translate the ID to use the root doc's namespaces 
+	my $node = shift;
+	foreach my $id ('id','before')
+		{
+		&fixID($node,$id);
+		}
+}
+
+sub idns
+	{ # return the namespace of an ID
+	my $node = shift;
+	my $id = shift;
+	if($id eq '' ) {$id = $node->getAttribute('id'); }
+	if($id=~s/^(.*)://)
+		{ # it's got a ns, find out what it is
+		my $pre = $1;
+		return ($id,&getNs($node,$pre));
+		}
+		return ($id,$node->getOwnerDocument->getDocumentElement->getAttribute("id-namespace") ||	$defaultns);
+	}
+
+sub fixID
+	{
+	# translate the ID to use the root doc's namespaces 
+	my $node = shift;
+	my $attr = shift || 'id';
+	my $id = $node->getAttribute($attr);
+	if($id eq '') {return}
+	my $ns;
+	if($id=~s/^(.*)://)
+		{ # it's got a ns, find out what it is
+		my $pre = $1;
+		$ns=&getNs($node,$pre);
+		}
+	else
+		{
+		$ns = $node->getOwnerDocument->getDocumentElement->getAttribute("id-namespace") ||
+			$defaultns;
+		}
+	$ns = $urimap{$ns};
+	$id = ($ns eq '') ? $id : "$ns:$id";
+	return $node->setAttribute($attr,$id);
+}
+
+sub firstElement {
+	# return the first element in this node
+	my $node = shift;
+	foreach my $item (@{$node->getChildNodes}) {
+		if($item->getNodeType==1) {return $item}
+	}
+}
+
+
+sub atts {
+	# return a hash of all attribtues defined for this element
+	my $node = shift;
+	my %at = $node->getAttributes;
+	my %list;
+	foreach my $a (keys %{$node->getAttributes}) 
+		{
+		if($a ne '')
+			{
+			$list{$a} = $node->getAttribute ($a);
+			}
+		}
+	return %list;
+}
+
+
+sub ns 
+	{
+	# return a hash of ns prefix and uri -- the xmlns: part is stripped off
+	my $node = shift;
+	my %list;
+	foreach my $a (keys %{$node->getAttributes}) 
+		{
+		my $pre = $a;
+		if($pre=~s/^xmlns://)
+			{
+			$list{$pre} = $node->getAttribute ($a);
+			}
+		}
+	return %list;
+	}
+
+
+
+sub namespaces
+	{
+	# return a list of namespace URI / prefix pairs, in the order they're defined
+	# these need to be used to define namespaces in the root element
+	my $file = shift;
+	my $node = shift;
+	my $type = $node->getNodeType;
+	if($type!=1) {return}
+	my $tag = $node->getTagName;
+	my @res;
+	my %nslist = &ns($node);
+	while(my($pre,$uri)=each(%nslist))
+		{ # push all namespaces defined here onto the list
+		push(@res,$uri,$pre);
+		}
+	if($tag=~/^(layer|package|collection|component)$/ )
+		{ # these have the potential of linking, so check for that
+		}
+	elsif($tag eq 'SystemDefinition' )
+		{
+		my $default = $node->getAttribute('id-namespace');
+		if($default)
+			{# mangle with a space so it's clear it's not a qname
+			push(@res,$default,'id namespace');
+			}
+		}
+	foreach my $item (@{$node->getChildNodes})
+		{
+		push(@res,&namespaces($file,$item));
+		}
+	return @res;
+	}
+
+sub  processMeta
+	{
+	my $metanode = shift;
+	# do nothing. Not supported yet
+	}
+
+sub guessIdInPath
+	{
+	my $id = shift;
+	my @path = reverse(split(/\//,shift));
+	while(@path)
+		{
+		my $dir = shift(@path);
+		if($dir eq $id)
+			{
+			return ($id,@path);
+			}
+		}
+	}
+
+
+sub parentPath
+	{
+	my $node=shift;
+	my @path;
+	while($node)
+		{
+		if(!$node) {return @path}
+		my $id=$node->getAttribute('id');
+		if($id eq '') {return @path}
+		$id=~s/^.*://;
+		@path = ($id,@path);
+		$node = $node->getParentNode();
+		}
+	return @path;
+	}
+
+sub childTag
+	{
+	my $tag = shift;
+	if($tag eq 'systemModel') {return 'layer'}
+	if($tag eq 'layer') {return 'package'}
+	if($tag eq 'package') {return 'collection'}
+	if($tag eq 'collection') {return 'component'}
+	die "ERROR: no child for $tag";
+	}
+
+sub appendNewItem
+	{
+	my $node = shift;
+	my $doc = $node->getOwnerDocument;
+	my $id = shift;
+	my $fullid=$id;
+	my $contents = shift;
+	my $tag = &childTag($node->getTagName());
+	my $new = $doc->createElement($tag);
+	if($id=~/^(.*) (.*)/)
+		{
+		$id=$1;
+		$ns = getNamespacePrefix($node,$2);
+		if($ns ne '') {$id="$ns:$id"}
+		}
+	else
+		{
+		$contents = '';
+		}
+	$new->setAttribute('id',$id);		# default namespace
+	$node->appendChild($new);
+	my $ppath =  join('/',&parentPath($new));
+	if($contents eq '')
+		{ # look for additions
+		print STDERR "$warning: Adding new $tag: $id\n";
+		if($newContainer{$ppath}) {
+			foreach my $item (sort keys %{$newContainer{$ppath}})
+				{
+				&appendNewItem($new,$item,$newContainer{$ppath}->{$item});
+				}
+			}
+		}
+	else
+		{ # this one item is defined in the specified file
+		if($tag eq 'package') 
+			{ #include some package data in root
+			my $fragment = $parser->parsefile ($contents);
+			my $fdoc = $fragment->getDocumentElement();
+			my $topmost =&firstElement($fdoc);
+			my %at = &atts($topmost);
+			foreach my $arg ('tech-domain','level','span')
+				{
+				if($at{$arg}) {	$new->setAttribute($arg,$at{$arg})}
+				}
+			if($at{'tech-domain'}) {&positionByTechDomain($new)}
+			}
+		&setHref($new,$contents);
+		print STDERR "$warning: Adding found $tag $id from $contents\n";
+		delete $replacing{$tag}->{$fullid};
+		}
+	# newline after each new tag so output's not ugly
+	if($new->getNextSibling)
+		{
+		$node->insertBefore($doc->createTextNode ("\n"),$new->getNextSibling);
+		}
+	else
+		{
+		$node->appendChild($doc->createTextNode ("\n"));
+		}
+	delete $newContainer{$ppath};
+	}
+
+
+sub getNamespacePrefix
+	{
+	my $node = shift;
+	my $ns = shift;
+	my $root = $node->getOwnerDocument->getDocumentElement;
+	my $idns = $root->getAttribute("id-namespace");
+	if($idns && $idns eq $ns) {return}
+	if(!$idns && $defaultns eq $ns) {return}
+	foreach my $a (keys %{$root->getAttributes}) 
+		{
+		my $pre = $a;
+		if($pre=~s/^xmlns://)
+			{
+			if($node->getAttribute ($a) eq $ns)  {return $pre}
+			}
+		}
+	die "ERROR: no namespace prefix defined for $ns";
+	}
+
+
+sub resolvePath
+	{
+	# return full path to 2nd arg relative to first (path or absolute URI)
+	my $base = shift;
+	my $path = shift;
+	if($path=~m,^/,) {return $path } # path is absolute, but has no drive. Let OS deal with it.
+	if($path=~s,^file:///([a-zA-Z]:/),$1,) {return $path } # file URI with drive letter
+	if($path=~m,^file://,) {return $path } # file URI with no drive letter (unit-style). Just pass on as is with leading / and let OS deal with it
+	if($path=~m,^[a-z0-9][a-z0-9]+:,i) {return $path } # absolute URI -- no idea how to handle, so just return
+	return &abspath(File::Basename::dirname($base)."/$path");
+	}
+
+
+sub fixHref {
+	my $node = shift;
+	my $base = shift;
+	my $link= $node->getAttribute('href');
+	if($link=~/^(ftp|http)s:\/\//) {return} # remote link, do nothing
+	my $path = &resolvePath($base,$link);
+	if(!-e $path) 
+		{ # no such file, delete
+		my $tag  =$node->getTagName;
+		my $id = $node->getAttribute('id');
+		print STDERR "$warning: $tag $id not found at $link\n";	
+		$node->getParentNode->removeChild($node);
+		return;
+		}
+	if($output eq '')
+		{
+		$path=~s,^/?,file:///,;
+		$node->setAttribute('href',$path);	# replace with absolute URI
+		return;
+		}
+	$node->setAttribute('href',&normpath($modpath.$link));	# make relative path to output file
+	}
+
+
+sub setHref {
+	my $node = shift;
+	my $file = shift;
+	if($output eq '') 
+		{
+		$path = &abspath($file);
+		$path=~s,^/?,file:///,;
+		$node->setAttribute('href',$path);	# replace with absolute URI
+		}
+	else 
+		{
+		$node->setAttribute('href',&relativeTo(&abspath($output),$file,'file'));
+		}
+}
+
+
+sub relativeTo {
+	if($_[0] eq '') {return &abspath($_[1])}
+	my @outfile = split(/[\\\/]/,lc(shift));
+	my @infile  = split(/[\\\/]/,lc(shift));
+	my $asdir = shift ne 'file';
+	while($outfile[0] eq $infile[0])
+		{
+		shift(@outfile);
+		shift(@infile);
+		}
+	$modpath = '../' x (scalar(@outfile) - 1);
+	if($asdir) {
+		if(scalar @infile > 1)  {$modpath .=  join('/',@infile[0..$#infile - 1]).'/'}
+	} else   {$modpath .=  join('/',@infile)}
+	return $modpath;
+}
+
+sub positionByTechDomain 
+	{
+	my $node=shift;
+	my $td = $node->getAttribute('tech-domain');
+	my %before;
+	foreach my $t (@tdOrder)
+		{
+		$before{$t}=1;
+		if($t eq $td) {last}
+		}
+	my $prev = $node->getPreviousSibling;
+	foreach my $child (reverse @{$node->getParentNode->getChildNodes})
+		{
+		if($child->getNodeType==1 && $child->getTagName eq 'package' && $child!=$node)
+			{
+			if($before{$child->getAttribute('tech-domain')})
+				{
+				my $next = $child->getNextSibling;
+				while($next &&  $next->getNodeType!=1) {$next = $next->getNextSibling}
+				if($next) {
+					$node->getParentNode->insertBefore ($node,$next);
+				}
+				last;
+				}
+			}
+		}
+	}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysdeftools/sysdefdowngrade.xsl	Tue Apr 06 10:25:29 2010 +0100
@@ -0,0 +1,425 @@
+<?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:
+	Downgrade a 3.x system definition into the 2.0.1 syntax
+-->
+	<xsl:output method="xml" indent="yes"/>
+	
+	<xsl:param name="Path">os/deviceplatformrelease/foundation_system/system_model</xsl:param>
+	<!-- $Path is the location of the root system definition XML file. Must not end in /
+		This is used to compute the absolute paths the 2.0 syntax needs-->
+	<xsl:param name="Root"/> <!-- space separated list of root variables in the form "VAR1=value1 VAR=value2" --> 
+	<xsl:variable name="root" select="concat(' ',$Root,' ')"/> <!-- sort of hack to allow absolute paths in downgraded output -->
+	<xsl:variable name="srcroot" select="substring-before(substring-after($root,' SRCROOT='),' ')"/> <!-- the default path prefix -->
+
+<xsl:template match="/*">
+	<xsl:message terminate="yes">ERROR: Cannot process this document</xsl:message>
+</xsl:template>
+
+<!-- can only handle 3.0.0 to 2.0.1 transforms
+	Assumes only packages are using href
+ -->
+<xsl:template match="/SystemDefinition[@schema='3.0.0']"> 
+	<!-- process root system definition or package definition-->
+	<xsl:call-template name="DTD"/> <!-- insert 2.0.01 DTD -->
+  <SystemDefinition name="{*/@name}" schema="2.0.1">
+  	<xsl:apply-templates select="*|comment()"/>
+  </SystemDefinition>
+</xsl:template>
+
+<xsl:template match="/SystemDefinition[@schema='3.0.0' and systemModel]"> 
+	<xsl:call-template name="DTD"/> <!-- insert 2.0.01 DTD -->
+  <SystemDefinition name="{systemModel/@name}" schema="2.0.1">
+  	<xsl:apply-templates select="*|comment()"/>
+  </SystemDefinition>
+</xsl:template>
+
+<xsl:template match="/SystemDefinition/package[@href]" priority="2">
+	<xsl:message terminate="yes">ERROR: Package definition (<xsl:value-of select="@id"/>) cannot link another package</xsl:message>
+</xsl:template>
+
+<xsl:template match="/SystemDefinition/package" priority="1">
+	<!-- process package definition file--> 
+  <systemModel>
+  	<layer name="anonymous"> <!-- fake layer -->
+		<block>
+			<xsl:apply-templates mode="copy" select="@id|@name|@span|@level|@levels"/><!--  valid attribuites for 2.0 -->
+		  	<xsl:apply-templates select="*|comment()">
+		  		<xsl:with-param name="path" select="concat($Path,'/')"/> <!-- need to keep tack of where the current document is -->
+		  	</xsl:apply-templates>			
+		</block>  
+   	</layer>
+  </systemModel>
+</xsl:template>
+
+
+
+<xsl:template match="/"><xsl:apply-templates select="*"/></xsl:template>
+<xsl:template match="@*|comment()"><xsl:copy-of select="."/></xsl:template> 
+	<!-- comments are copied verbatim. Attribtues are copied by default -->
+
+<xsl:template match="systemModel">
+	<systemModel>
+  	<xsl:apply-templates select="*|comment()"> <!-- no attributes -->
+  		<xsl:with-param name="path" select="$Path"/> <!-- need to keep tack of where the current document is -->
+  	</xsl:apply-templates>
+	</systemModel>
+</xsl:template>
+
+<xsl:template mode="copy" match="@*">
+	<xsl:copy-of select="."/>
+</xsl:template>
+
+<xsl:template mode="copy" match="@id"> <!-- id in 3.0 is name in 2.0 -->
+	<xsl:attribute name="name"><xsl:value-of select="."/></xsl:attribute>
+</xsl:template>
+
+<xsl:template mode="copy" match="@name">  <!-- name in 3.0 is long-name in 2.0.1 -->
+	<xsl:if test=".!=../@id"> <!-- don't bother if it will be the same as name -->
+		<xsl:attribute name="long-name"><xsl:value-of select="."/></xsl:attribute>
+	</xsl:if>
+</xsl:template>
+	
+<xsl:template match="layer"><xsl:param name="path"/>
+	<layer>
+		<xsl:apply-templates mode="copy" select="@id|@name|@span|@levels"/> <!--  valid attribuites for 2.0 -->
+		<xsl:apply-templates select="*|comment()"> 
+			<xsl:with-param name="path" select="$path"/> 
+		</xsl:apply-templates>
+	</layer>
+</xsl:template>
+
+<xsl:template match="layer/package"><!-- translates to block -->
+	<xsl:param name="path"/>
+	<block>
+		<xsl:apply-templates mode="copy" select="@id|@name|@span|@level|@levels"/><!--  valid attribuites for 2.0 -->
+		<xsl:choose>
+			<xsl:when test="@href">
+				<xsl:variable name="this" select="."/>
+				<xsl:variable name="prefixmap" select="ancestor::SystemDefinition/*/meta[@rel='link-mapping']/map-prefix[starts-with(current()/@href,@link)]"/>
+				<xsl:for-each select="document(@href,.)/SystemDefinition/*">
+					<xsl:variable name="my-id"><xsl:apply-templates mode="normalize-id" select="@id"/></xsl:variable>
+					<xsl:variable name="other-id"><xsl:apply-templates mode="normalize-id" select="$this/@id"/></xsl:variable>
+					<xsl:if test="$my-id != $other-id">
+						<xsl:message terminate="yes">ERROR: Package IDs do not match: <xsl:value-of select="$my-id"/> vs <xsl:value-of select="$other-id"/></xsl:message>
+					</xsl:if>
+					<xsl:if test="@name and @name!=@id and not($this/@name and $this/@name=$this/@id)">
+						<!-- set long-name only if name is different from the id and not set in child doc -->
+						<xsl:attribute name="long-name"><xsl:value-of select="@name"/></xsl:attribute>
+					</xsl:if>						
+					<xsl:for-each select="@span|@levels|@level">
+						<!-- copy only if not set in child doc -->
+						<xsl:if test="not(this/@*[name()=name(current())])">
+							<xsl:copy-of select="."/>
+						</xsl:if>
+					</xsl:for-each>
+					<xsl:apply-templates select="*|comment()">
+	  					<xsl:with-param name="path">
+							<xsl:choose>
+								<xsl:when test="$prefixmap">
+	  								<xsl:call-template name="normpath">
+	  									<xsl:with-param name="path">
+										<xsl:apply-templates select="$prefixmap/@to"/>
+										<xsl:value-of select="substring-after($this/@href,$prefixmap/@link)"/>
+									 </xsl:with-param>
+	  								</xsl:call-template>
+								</xsl:when>
+								<xsl:when test="starts-with($this/@href,'/')">  <!-- absolute path -->
+	  								<xsl:call-template name="normpath">
+	  									<xsl:with-param name="path" select="$this/@href"/>
+	  								</xsl:call-template>
+								</xsl:when>
+								<xsl:when test="contains($this/@href,'://')">  <!-- generic URI -->
+	  								<xsl:call-template name="normpath">
+	  									<xsl:with-param name="path" select="substring-after($this/@href,'://')"/>
+	  								</xsl:call-template>
+								</xsl:when>
+								<xsl:otherwise>
+	  								<xsl:call-template name="normpath">
+	  									<xsl:with-param name="path" select="concat($path,'/',$this/@href)"/>
+	  								</xsl:call-template>
+								</xsl:otherwise>
+							</xsl:choose>
+	  					</xsl:with-param> 
+	  				</xsl:apply-templates>
+				</xsl:for-each>
+			</xsl:when>
+			<xsl:otherwise>
+				<xsl:apply-templates select="*|comment()">
+  					<xsl:with-param name="path" select="$path"/> 
+  				</xsl:apply-templates>
+			</xsl:otherwise>
+		</xsl:choose>
+	</block>
+</xsl:template>
+
+<xsl:template match="package/package">	<!-- translates to subblock --><xsl:param name="path"/>
+	<subblock>
+		<xsl:apply-templates mode="copy" select="@id|@name"/>
+		<xsl:apply-templates select="*|comment()">
+			<xsl:with-param name="path" select="$path"/> 
+		</xsl:apply-templates>
+	</subblock>
+</xsl:template>
+
+<xsl:template match="package/package/pacakge"> <!-- cannot nest this deep --><xsl:param name="path"/>
+	<xsl:message>WARNING: Excessive nesting of packages: Ignoring <xsl:value-of select="@id"/></xsl:message>
+	<xsl:apply-templates select="*|comment()">
+		<xsl:with-param name="path" select="$path"/> 
+	</xsl:apply-templates>
+</xsl:template>
+
+
+<xsl:template match="collection"><xsl:param name="path"/>
+	<collection>
+		<xsl:apply-templates mode="copy" select="@id|@name|@level"/>
+		<xsl:apply-templates select="*|comment()">
+			<xsl:with-param name="path" select="$path"/> 
+		</xsl:apply-templates>
+	</collection>
+</xsl:template>
+
+
+<xsl:template match="component"><xsl:param name="path"/>
+	<component>
+		<xsl:apply-templates mode="copy" select="@id|@name|@deprecated|@introduced|@filter|@purpose"/>
+		<xsl:if test="contains(concat(' ',@class,' '),' plugin ')">
+			<xsl:attribute name="plugin">Y</xsl:attribute>
+		</xsl:if>
+		<xsl:call-template name="class">
+			<xsl:with-param name="remove">plugin</xsl:with-param>
+			<xsl:with-param name="add">
+				<xsl:if test="not(*) and comment()">placeholder</xsl:if>
+				<xsl:if test="@target='desktop'"> PC</xsl:if>
+			</xsl:with-param>
+		</xsl:call-template>
+	  	<xsl:apply-templates select="*|comment()">
+			<xsl:with-param name="path" select="$path"/> 
+		</xsl:apply-templates>
+	</component>
+</xsl:template>
+
+<xsl:template match="unit[@base and not(@mrp or @bldFile)]"/>
+
+<xsl:template match="unit"><xsl:param name="path"/>
+	<unit>
+		<xsl:apply-templates select="@mrp|@bldFile|@late">
+			<xsl:with-param name="path" select="$path"/> 
+		</xsl:apply-templates>
+		<xsl:copy-of select="@filter|@root[not(contains($root,concat(' ',.,'=')))]|@version|@prebuilt|@priority"/>
+	</unit>
+</xsl:template>
+
+<xsl:template match="unit/@late"> <!-- 2.0 uses Y/N, 3.0 uses yes/no -->
+	<xsl:attribute name="{name()}">
+		<xsl:choose>
+			<xsl:when test=".='yes'">Y</xsl:when>
+			<xsl:when test=".='no'">N</xsl:when>
+		</xsl:choose>
+	</xsl:attribute>
+</xsl:template>
+
+<xsl:template match="@mrp|@bldFile"><xsl:param name="path"/>
+	<xsl:attribute name="{name()}">
+		<xsl:choose>
+			<xsl:when test="../@root">
+				<xsl:variable name="pre" select="substring-before(substring-after($root,concat(' ',../@root,'=')),' ')"/>
+				<xsl:value-of select="$pre"/>
+				<xsl:if test="$pre!='' and $pre!='/'">/</xsl:if>
+			</xsl:when>
+			<xsl:when test="$srcroot='/'"> <!-- treat all paths as absolute -->
+				<xsl:value-of select="$srcroot"/>
+			</xsl:when>
+			<xsl:when test="$srcroot!=''">
+				<xsl:value-of select="concat($srcroot,'/')"/>
+			</xsl:when>
+		</xsl:choose>
+		<xsl:choose>
+		<xsl:when test="starts-with(.,'/')"> <!-- keep absolute paths verbatim (barring the leading / ) -->
+			<xsl:value-of select="substring-after(.,'/')"/>
+		</xsl:when>
+		<xsl:otherwise>	
+			<xsl:call-template name="normpath">
+  				<xsl:with-param name="path">
+  					<xsl:call-template name="before">
+						<xsl:with-param name="text" select="$path"/>
+					</xsl:call-template>
+					<xsl:value-of select="."/>
+  				</xsl:with-param>
+  			</xsl:call-template>
+		</xsl:otherwise>
+	</xsl:choose>
+	</xsl:attribute>
+</xsl:template>
+
+<xsl:template match="meta"/> <!-- strip all meta tags -->
+
+<xsl:template match="meta[info/@contract]"> <!-- except contract -->
+	<xsl:copy-of select="info/@contract"/>
+</xsl:template>
+
+
+<xsl:template match="meta[@rel='link-mapping']/map-prefix/@to">
+	<xsl:choose>
+		<xsl:when test="starts-with(.,'/')"><xsl:value-of select="substring(.,2)"/></xsl:when> <!-- absolute paths in 3.0 are relative in 2.0 -->
+		<xsl:otherwise><xsl:value-of select="."/></xsl:otherwise>
+	</xsl:choose>
+</xsl:template>
+
+
+<xsl:template match="@id" mode="normalize-id">
+	<xsl:choose>
+		<xsl:when test="contains(@id,':')"><xsl:value-of select="substring-after(@id,':')"/></xsl:when>
+		<xsl:otherwise><xsl:value-of select="@id"/></xsl:otherwise>
+	</xsl:choose>
+</xsl:template>
+
+<xsl:template name="class"><xsl:param name="remove"/><xsl:param name="add"/>
+<!--  returns the value of the class attribute with the space-separated list of names in $remove taken out and those in $add added on (does not check for duplicates) -->
+	<xsl:param name="class" select="normalize-space(@class)"/>
+	<xsl:variable name="r">
+		<xsl:text> </xsl:text>
+		<xsl:choose>
+			<xsl:when test="contains($remove,' ')"><xsl:value-of select="substring-before($remove,' ')"/></xsl:when>
+			<xsl:otherwise><xsl:value-of select="$remove"/></xsl:otherwise>
+		</xsl:choose>
+		<xsl:text> </xsl:text>
+	</xsl:variable>
+	<xsl:variable name="c">
+		<xsl:choose>
+			<xsl:when test="contains(concat(' ',$class,' '),$r)">
+				<xsl:value-of select="substring-before(concat(' ',$class,' '),$r)"/>
+				<xsl:text> </xsl:text>
+				<xsl:value-of select="substring-after(concat(' ',$class,' '),$r)"/>
+			</xsl:when>
+			<xsl:otherwise><xsl:value-of select="$class"/></xsl:otherwise>
+		</xsl:choose>
+		<xsl:if test="normalize-space($add)!=''"><xsl:value-of select="concat(' ',normalize-space($add))"/></xsl:if>
+	</xsl:variable>
+	<xsl:choose>
+		<xsl:when test="contains($remove,' ')">
+			<xsl:call-template name="class">
+				<xsl:with-param name="remove" select="substring-after($remove,' ')"/>
+				<xsl:with-param name="class" select="$c"/>
+			</xsl:call-template>
+		</xsl:when>
+		<xsl:when test="normalize-space($c)!=''">
+			<xsl:attribute name="class">
+				<xsl:value-of select="normalize-space($c)"/>
+			</xsl:attribute>
+		</xsl:when>
+	</xsl:choose>
+</xsl:template>
+
+<xsl:template name="normpath"><xsl:param name="path"/>
+<!-- normalize out any ".." in the path in $path  -->
+<xsl:choose>
+	<xsl:when test="contains($path,'/../')">
+	<xsl:call-template name="normpath">
+		<xsl:with-param name="path">
+		<xsl:call-template name="before">
+			<xsl:with-param name="text" select="substring-before($path,'/../')"/>
+		</xsl:call-template>
+		<xsl:value-of select="substring-after($path,'/../')"/>
+		</xsl:with-param>
+		</xsl:call-template>
+	</xsl:when>
+	<xsl:otherwise><xsl:value-of select="$path"/></xsl:otherwise>
+</xsl:choose>
+</xsl:template>
+
+<!-- return all text before the last / -->
+<xsl:template name="before"><xsl:param name="text"/>
+<xsl:if test="contains($text,'/')">
+	<xsl:value-of select="substring-before($text,'/')"/>/<xsl:call-template name="before"><xsl:with-param name="text" select="substring-after($text,'/')"/></xsl:call-template>
+	</xsl:if>
+</xsl:template>
+
+<xsl:template name="DTD">
+<xsl:text disable-output-escaping="yes"><![CDATA[<!DOCTYPE SystemDefinition [
+<!ELEMENT SystemDefinition ( systemModel )>
+<!ATTLIST SystemDefinition
+  name CDATA #REQUIRED
+  schema CDATA #REQUIRED
+>
+<!-- all paths are relative to the environment variable specified by the root attribute, or SOURCEROOT if not.  -->
+
+<!-- System Model Section of DTD -->
+<!ELEMENT systemModel (layer+)>
+
+<!ELEMENT layer (block* | collection*)*>
+<!-- Kernel Services, Base Services, OS Services, Etc -->
+<!ATTLIST layer
+  name CDATA #REQUIRED
+  long-name CDATA #IMPLIED
+  levels NMTOKENS #IMPLIED
+  span CDATA #IMPLIED
+>
+
+<!ELEMENT block (subblock* | collection*)*>
+ <!-- Generic OS services, Comms Services, etc -->
+<!ATTLIST block
+  levels NMTOKENS #IMPLIED
+  span CDATA #IMPLIED
+  level NMTOKEN #IMPLIED
+  name CDATA #REQUIRED
+  long-name CDATA #IMPLIED
+>
+
+<!ELEMENT subblock (collection)*>
+<!-- Cellular Baseband Services, Networking Services, etc -->
+<!ATTLIST subblock
+  name CDATA #REQUIRED
+  long-name CDATA #IMPLIED
+>
+
+<!ELEMENT collection (component)*>
+<!-- Screen Driver, Content Handling, etc -->
+<!ATTLIST collection
+  name CDATA #REQUIRED
+  long-name CDATA #IMPLIED
+  level NMTOKEN #IMPLIED
+>
+
+<!ELEMENT component (unit)*>
+<!-- contains units or is a  package or prebuilt -->
+<!ATTLIST component
+  name CDATA #REQUIRED
+  long-name CDATA #IMPLIED
+  deprecated CDATA #IMPLIED
+  introduced CDATA #IMPLIED
+  contract CDATA #IMPLIED
+  plugin (Y|N) "N"
+  filter CDATA #IMPLIED
+  class NMTOKENS #IMPLIED
+  supports CDATA #IMPLIED
+  purpose ( optional | mandatory | development ) "optional"
+>
+
+<!ELEMENT unit EMPTY >
+<!-- must be buildable (bld.inf) -->
+<!-- bldFile  may someday be removed in favour of mrp -->
+<!ATTLIST unit
+  mrp CDATA #IMPLIED
+  filter CDATA #IMPLIED
+  bldFile CDATA #IMPLIED
+  root CDATA #IMPLIED
+  version NMTOKEN #IMPLIED
+  prebuilt NMTOKEN #IMPLIED
+  late (Y|N) #IMPLIED
+  priority CDATA #IMPLIED
+>
+]>
+]]></xsl:text>
+</xsl:template>
+</xsl:stylesheet>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysdeftools/validate/checklinks.pl	Tue Apr 06 10:25:29 2010 +0100
@@ -0,0 +1,108 @@
+# 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:
+# Script to validate the unit links in a system definition or package definition XML file
+
+use strict;
+
+if (! scalar @ARGV) {&help()}
+
+
+my $debug = 0;
+my $skipfilter;	# skip anything with a named filter
+my $xslt = "../../../buildtools/bldsystemtools/buildsystemtools/joinsysdef.xsl";
+my $xalan = "../../../buildtools/devlib/devlibhelp/tools/doc_tree/lib/apache/xalan.jar";
+my $sysdef = shift;
+while($sysdef=~/^-/) { #arguments
+	 if($sysdef eq '-nofilter') {$skipfilter = shift}
+	 elsif($sysdef eq '-v') {$debug = 1}
+	 else { &help("Invalid command line option $sysdef")} 
+	 $sysdef = shift; 
+}
+my $dir = $sysdef;
+$dir =~ s,[^\\/]+$,,;
+my $root="../../../..";
+ my $full;
+ 
+if($sysdef=~/system_definition\.xml/) {	# if running on a sysdef, ensure it's joined before continuing
+	($full = `java -jar $dir$xalan -in $sysdef -xsl $dir$xslt`) || die "bad XML syntax";
+}else {	# assume any other file has no hrefs to include (valid by convention)
+	$root='';
+	open S, $sysdef;
+	$full=join('',<S>);
+	close S;
+}
+$full=~s/<!--.*?-->//sg; # remove all comments;
+my $count=1;
+
+my $filter = '';
+foreach (split(/</,$full)) {	# loop through all elements
+	my $found = 0;
+	if(/^component/) {		# save the current filter so we know if we need to skip the named filter
+		$filter='';
+		if(/filter="([^"]+)"/) {$filter=$1}
+	}
+	elsif(s/^unit//) {
+		my $f=",$filter,";		# commas are the separators - safe to have extra ones for testing
+		if(/filter="([^"]+)"/) {$f.=",$1,"}
+		if($skipfilter ne '' && $f=~/,$filter,/) {next}	# don't test anything with s60 filter
+		if(/\smrp="(.*?)"/) {
+			my $file = &fileLocation($1);
+			if($debug) {print "MRP ",-s $file," $file\n"}		# debug code		
+			if(!(-s $file)){
+				print  STDERR "$count: Cannot find MRP file $file\n";	
+				$found=1;
+			}
+		}
+		if(/\sbldFile="(.*?)"/) {
+			my $file = &fileLocation("$1/bld.inf");
+			if($debug) {print "Bld ",-s $file ," $file\n"}		# debug code		
+			if(!(-s $file) ){
+				print  STDERR "$count: Cannot find bld.inf file $file\n";
+				$found=1;
+			}
+		}
+		if(/\sbase="(.*?)"/) {
+			my $file = &fileLocation($1);
+			if($debug) {print "Base $file\n"}		# debug code		
+			if(!(-d $file) ){
+				print  STDERR "$count: Cannot find base dir $file\n";
+				$found=1;
+			}
+		}
+	}	
+	$count+=$found;	
+}
+
+exit $count;
+
+sub fileLocation {
+	my $file = "$dir$root$_[0]";
+	$file=~tr/\//\\/;
+	while($file=~s/\\[^\\.]+\\\.\.\\/\\/){}
+	return $file;
+}
+sub help {
+	print "$0: ",($_[0] eq '' ? "syntax"  : $_[0]); 
+	print "\nSyntax: [-v] [-nofilter filter] system_definition.xml 
+Validate the unit links in a system definition or package definition XML
+file. This only prints errors in the files. If it exits silently, the links
+are all valid.
+	Call with -nos60 filter to skip checking presence of fitler=\"s60\" units
+	Requires system definition files to be in the standard location
+	in deviceplatformrelease,
+	and the presence of joinsysdef.xsl and xalan.jar in their expected
+	locations.
+	Package definition files can be anywhere.";
+exit 1;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysdeftools/validate/modelcheck.xsl	Tue Apr 06 10:25:29 2010 +0100
@@ -0,0 +1,71 @@
+<xsl:stylesheet  xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
+<!--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:
+	Validate a system definition file or files and output results in HTML
+-->
+	<xsl:output method="html"/>
+	<xsl:include href="test-model.xsl"/>
+<xsl:template match="/model">
+	<html><head>
+		<title>Cross-Checking System Model</title>
+		<style>p {margin: 0px; padding: 0px} 
+			p.warn span {color: blue}
+			p.note span {color: green}
+			p.err span {font-weight: bold}
+			p.err {color: red; background: yellow}
+			p.note {font-size: 90%}
+			<xsl:if test="contains(concat(' ',normalize-space(/model/@supress-errors),' '),' note ')">
+				p.note {display: none}
+			</xsl:if>
+			<xsl:if test="contains(concat(' ',normalize-space(/model/@supress-errors),' '),' err ')">
+				p.err {display: none}
+			</xsl:if>
+			<xsl:if test="contains(concat(' ',normalize-space(/model/@supress-errors),' '),' warn ')">
+				p.warn {display: none}
+			</xsl:if>
+		</style>
+	</head><body>
+	<xsl:apply-templates select="." mode="check"/>
+	</body></html>
+</xsl:template>
+
+
+<xsl:template name="Section"><xsl:param name="text"/><xsl:param name="sub"/>
+<h2><xsl:value-of select="$text"/>
+<xsl:if test="$sub!=''"><xsl:text> </xsl:text> <small>(<xsl:value-of select="$sub"/>)</small></xsl:if></h2>
+</xsl:template>
+
+<xsl:template name="Note"><xsl:param name="text"/><xsl:param name="sub"/>
+<p class="note">
+	<span>Note:</span>
+	<xsl:text> </xsl:text>
+	<xsl:copy-of select="$text"/>
+<xsl:if test="$sub!=''"><xsl:text> </xsl:text> <small>(<xsl:value-of select="$sub"/>)</small></xsl:if></p>
+</xsl:template>
+
+<xsl:template name="Warning"><xsl:param name="text"/><xsl:param name="sub"/>
+<p class="warn">
+	<span>Warning:</span>
+	<xsl:text> </xsl:text>
+	<xsl:value-of select="$text"/>
+<xsl:if test="$sub!=''"><xsl:text> </xsl:text> <small>(<xsl:value-of select="$sub"/>)</small></xsl:if></p>
+</xsl:template>
+
+<xsl:template name="Error"><xsl:param name="text"/><xsl:param name="sub"/>
+<p class="err">
+	<span>Error:</span>
+	<xsl:text> </xsl:text>
+	<xsl:value-of select="$text"/>
+<xsl:if test="$sub!=''"><xsl:text> </xsl:text> <small>(<xsl:value-of select="$sub"/>)</small></xsl:if></p>
+</xsl:template>
+
+</xsl:stylesheet>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysdeftools/validate/test-model.xsl	Tue Apr 06 10:25:29 2010 +0100
@@ -0,0 +1,490 @@
+<xsl:stylesheet  xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
+<!--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:
+	Module containing the validation logic for system definition 3.0.0 syntax
+-->
+	<xsl:key name="named" match="*[ancestor::systemModel]" use="@name"/>
+	<xsl:param name="Filename"/>
+	<xsl:variable name="info" select="document(/model//info[@type='extra']/@href,/model)//c"/>
+
+	<xsl:variable name="all-ids">
+		<xsl:apply-templates select="document(/model/sysdef/@href)| SystemDefinition" mode="ids"/>
+	</xsl:variable>
+
+ 
+<xsl:template match="/model" priority="-1">
+	<xsl:apply-templates select="." mode="check"/>
+</xsl:template>
+
+<xsl:template match="/model" mode="check">
+	<xsl:for-each select="sysdef">
+		<xsl:apply-templates select="document (@href,. )/*">
+			<xsl:with-param name="filename">
+				<xsl:choose>
+					<xsl:when test="starts-with(current()/@href,current()/@rootpath)">
+						<xsl:value-of select="substring-after(current()/@href,current()/@rootpath)"/>
+					</xsl:when>
+					<xsl:otherwise>
+						<xsl:value-of select="@href"/>
+					</xsl:otherwise>
+				</xsl:choose>
+			 </xsl:with-param>
+		</xsl:apply-templates>
+	</xsl:for-each>
+
+
+
+<xsl:apply-templates mode="x-check" select="document (//info[@type='vp']/@href)/*">
+	<xsl:with-param name="sysdef" select="document (sysdef/@href)/*"/>
+</xsl:apply-templates>
+
+<xsl:apply-templates mode="x-check" select="document (//info[@type='build']/@href)/*">
+	<xsl:with-param name="sysdef" select="document (sysdef/@href)/*"/>
+</xsl:apply-templates>
+</xsl:template>
+
+<xsl:template match="/SystemDefinition[@schema='3.0.0']" mode="ids">
+	<xsl:for-each select="//*[@id and not(@href)]"><xsl:value-of select="concat(' ',@id,' ')"/></xsl:for-each>
+	<xsl:apply-templates select="document(//layer/@href | //package/@href | //collection/@href | //component/@href,.)/*" mode="ids"/>
+</xsl:template>
+
+<xsl:template match="/SystemDefinition[@schema='3.0.0' and systemModel]" priority="2">
+	<xsl:param name="filename" select="$Filename"/>
+<xsl:call-template name="Section">
+	<xsl:with-param name="text">System Definition: <xsl:value-of select="*/@name"/></xsl:with-param>
+	<xsl:with-param name="sub"><xsl:value-of select="(string-length($all-ids) - string-length(translate($all-ids,' ',''))) div 2 "/> items</xsl:with-param>
+</xsl:call-template>
+	<xsl:apply-templates select="*">
+		<xsl:with-param name="filename" select="$filename"/>
+	</xsl:apply-templates>
+</xsl:template>
+
+<xsl:template match="/SystemDefinition[@schema='3.0.0'] | systemModel">
+	<xsl:param name="filename"  select="$Filename"/>
+		
+<xsl:if test="//unit">
+<xsl:call-template name="Section">
+	<xsl:with-param name="text"><xsl:value-of select="translate(substring(name(*),1,1),'clp','CLP')"/><xsl:value-of select="substring(name(*),2)"/> Definition: <xsl:value-of select="*/@name"/></xsl:with-param>
+	<xsl:with-param name="sub"><xsl:value-of select="count(//unit)"/> unit<xsl:if test="count(//unit)!=1">s</xsl:if></xsl:with-param>
+</xsl:call-template>
+</xsl:if>
+<xsl:if test="self::systemModel and not(@name)">
+	<xsl:call-template name="Error"><xsl:with-param name="text">systemModel element should have a name</xsl:with-param></xsl:call-template>
+</xsl:if>
+	<xsl:apply-templates select="*">
+		<xsl:with-param name="filename" select="$filename"/>
+	</xsl:apply-templates>
+</xsl:template>
+
+
+<xsl:template match="@*" mode="valid">
+	<xsl:call-template name="Error"><xsl:with-param name="text">Attribute <xsl:value-of select="name()"/>="<xsl:value-of select="."/>" is not valid for <xsl:value-of select="name(..)"/></xsl:with-param></xsl:call-template>
+</xsl:template>
+
+<xsl:template match="@before|@id|package/@span|collection/@level|package/@level|package/@levels|layer/@levels" mode="valid"/> <!-- really should check syntax -->
+
+<xsl:template match="@name|@href|@filter" mode="valid"/> 
+
+<xsl:template match="component/@introduced|component/@deprecated" mode="valid"/> 
+
+
+<xsl:template name="validate-class">
+	<ok>plugin</ok>
+	<ok>doc</ok>
+	<ok>tool</ok>
+	<ok>config</ok>
+	<ok>api</ok>
+	<w d="deprecated">test</w>
+</xsl:template>
+
+<xsl:template name="validate-purpose">
+	<ok>mandatory</ok>
+	<ok>optional</ok>
+	<ok>development</ok>
+</xsl:template>
+<xsl:template name="validate-target">
+	<ok>other</ok>
+	<ok>desktop</ok>
+	<ok>device</ok>
+</xsl:template>
+
+
+<xsl:template name="validate-tech-domain">
+	<ok>lo</ok>
+	<ok>hb</ok>
+	<ok>mm</ok>
+	<ok>ma</ok>
+	<ok>pr</ok>
+	<ok>vc</ok>
+	<ok>se</ok>
+	<ok>ui</ok>
+	<ok>dc</ok>
+	<ok>de</ok>
+	<ok>dm</ok>
+	<ok>rt</ok>
+	<ok>to</ok>
+	<w d="Non-standard">ocp</w>
+</xsl:template>
+
+<xsl:template match="component/@class" mode="valid">
+	<xsl:call-template name="checklist">
+		<xsl:with-param name="list" select="normalize-space(.)"/>
+		<xsl:with-param name="values" select="document('')/*/xsl:template[@name=concat('validate-',name(current()))]/*"/>
+	</xsl:call-template>
+</xsl:template> 
+
+<xsl:template name="checklist">
+	<xsl:param name="list" select="."/><xsl:param name="values"/><xsl:param name="sep" select="' '"/>
+	<xsl:variable name="item">
+		<xsl:choose>
+			<xsl:when test="contains($list,$sep)"><xsl:value-of select="substring-before($list,$sep)"/></xsl:when>
+			<xsl:otherwise><xsl:value-of select="$list"/></xsl:otherwise>
+		</xsl:choose>
+	</xsl:variable>
+	<xsl:variable name="v" select="$values[.=$item]"/>
+	<xsl:choose>
+		<xsl:when test="not($v)">
+			<xsl:call-template name="Error"><xsl:with-param name="text">Illegal <xsl:value-of select="name()"/> value <xsl:value-of select="name()"/>="<xsl:value-of select="."/>"</xsl:with-param></xsl:call-template>
+		</xsl:when> 
+		<xsl:when test="name($v)='ok'"/> 
+		<xsl:when test="name($v)='w'">
+			<xsl:call-template name="Warning"><xsl:with-param name="text"><xsl:value-of select="$v/@d"/> value in <xsl:value-of select="name()"/>="<xsl:value-of select="."/>"</xsl:with-param></xsl:call-template>
+		</xsl:when> 
+	</xsl:choose>	
+	<xsl:if test="contains($list,$sep)">
+		<xsl:call-template name="checklist">
+			<xsl:with-param name="list" select="substring-after($list,$sep)"/>
+			<xsl:with-param name="values" select="$values"/>
+			<xsl:with-param name="sep" select="$sep"/>			
+		</xsl:call-template>
+	</xsl:if>
+</xsl:template> 
+
+
+<xsl:template match="package/@tech-domain|component/@purpose|component/@target" mode="valid">
+	<xsl:variable name="v" select="document('')/*/xsl:template[@name=concat('validate-',name(current()))]/*[.=current()]"/>
+	<xsl:choose>
+		<xsl:when test="not($v)">
+			<xsl:call-template name="Error"><xsl:with-param name="text">Illegal <xsl:value-of select="name()"/> value <xsl:value-of select="name()"/>="<xsl:value-of select="."/>"</xsl:with-param></xsl:call-template>
+		</xsl:when> 
+		<xsl:when test="name($v)='ok'"/> 
+		<xsl:when test="name($v)='w'">
+			<xsl:call-template name="Warning"><xsl:with-param name="text"><xsl:value-of select="$v/@d"/> value in <xsl:value-of select="name()"/>="<xsl:value-of select="."/>"</xsl:with-param></xsl:call-template>
+		</xsl:when> 
+	</xsl:choose>
+</xsl:template> 
+
+
+
+
+
+<xsl:template match="*" priority="-2">
+	<xsl:call-template name="Error"><xsl:with-param name="text">Element "<xsl:value-of select="name()"/>" is not valid in the context of "<xsl:value-of select="name(..)"/>"</xsl:with-param></xsl:call-template>
+</xsl:template>
+
+<xsl:template match="component[not(parent::collection)] | collection[not(parent::package)] | package[not(parent::package or parent::layer or (parent::SystemDefinition and count(../*)=1))] | layer[not(parent::systemModel)] " priority="3">
+	<xsl:call-template name="Error"><xsl:with-param name="text"><xsl:value-of select="name()"/> "<xsl:value-of select="@id"/>" has invalid parent <xsl:value-of select="name(..)"/> "<xsl:value-of select="../@id"/>"</xsl:with-param></xsl:call-template>
+</xsl:template>
+
+<xsl:template match="layer | package | collection | component">
+	<xsl:param name="filename"/>
+
+<xsl:apply-templates select="@*" mode="valid"/>
+<xsl:apply-templates select="@id"/>
+<xsl:if test="self::component">
+	<xsl:choose>
+		<xsl:when test="count(*[not(@version)]) &gt; 1 and @filter='s60'">
+			<xsl:call-template name="Warning"><xsl:with-param name="text">S60 Component "<xsl:value-of select="@id"/>" has <xsl:value-of select="count(*)"/> children.</xsl:with-param></xsl:call-template>
+		</xsl:when>
+		<xsl:when test="count(*[not(@version)]) &gt; 1">
+			<xsl:call-template name="Error"><xsl:with-param name="text">Component "<xsl:value-of select="@id"/>" has <xsl:value-of select="count(*)"/> children.</xsl:with-param></xsl:call-template>
+		</xsl:when>
+	</xsl:choose>
+	<xsl:choose>
+		<xsl:when test="unit"/>
+		<xsl:when test="contains(comment(),'PLACEHOLDER=')"/>
+		<xsl:when test="comment()">
+			<xsl:call-template name="Note"><xsl:with-param name="text">Component "<xsl:value-of select="@name"/>" is empty.</xsl:with-param></xsl:call-template>
+		</xsl:when>
+		<xsl:when test="not(comment())">
+			<xsl:call-template name="Warning"><xsl:with-param name="text">Component "<xsl:value-of select="@name"/>" is empty and has no comment</xsl:with-param></xsl:call-template>
+		</xsl:when>
+	</xsl:choose>
+</xsl:if>
+<xsl:if test="@href">
+	<xsl:variable name="child" select="document(@href,.)/SystemDefinition"/>
+	<xsl:if test="@id!=$child/@id">
+		<xsl:call-template name="Error"><xsl:with-param name="text"><xsl:value-of select="name()"/> "<xsl:value-of select="@id"/>" must match ID in linked file "<xsl:value-of select="@href"/>"</xsl:with-param></xsl:call-template>
+	</xsl:if>
+	<xsl:if test="$child/@href">
+		<xsl:call-template name="Error"><xsl:with-param name="text">linked <xsl:value-of select="name()"/> "<xsl:value-of select="@id"/>" cannot be a link</xsl:with-param></xsl:call-template>
+	</xsl:if>
+	<xsl:for-each select="@*[name()!='id']">
+		<xsl:if test="$child/@*[name()=name(current())]">
+			<xsl:call-template name="Warning"><xsl:with-param name="text">linked <xsl:value-of select="name()"/> "<xsl:value-of select="@id"/>" has duplicate attribute to linking document. Duplicate ignored.</xsl:with-param></xsl:call-template>
+		</xsl:if>
+	</xsl:for-each>
+	<xsl:if test="*">
+		<xsl:call-template name="Error"><xsl:with-param name="text"><xsl:value-of select="name()"/> "<xsl:value-of select="@id"/>" cannot have both link and content. Content ignored.</xsl:with-param></xsl:call-template>
+	</xsl:if>
+</xsl:if>
+<xsl:if test="@href and name()!=name(document(@href,.)/SystemDefinition/*)">
+		<xsl:call-template name="Error"><xsl:with-param name="text"><xsl:value-of select="name()"/> "<xsl:value-of select="@id"/>" must match item in linked file "<xsl:value-of select="@href"/>"</xsl:with-param></xsl:call-template>
+</xsl:if>
+<xsl:if test="not(@href)">
+	<xsl:apply-templates select="*">
+		<xsl:with-param name="filename" select="$filename"/>
+	</xsl:apply-templates>
+</xsl:if>
+<xsl:if test="@href">
+	<xsl:apply-templates select="document(@href,.)/*">
+		<xsl:with-param name="filename">
+			<xsl:call-template name="normpath">
+				<xsl:with-param name="path">
+					<xsl:if test="not(starts-with(current()/@href,'/'))">
+						<xsl:call-template name="before">
+							<xsl:with-param name="text" select="$filename"/>
+						</xsl:call-template>
+					</xsl:if>
+					<xsl:value-of select="current()/@href"/>
+				 </xsl:with-param>
+			</xsl:call-template>
+		 </xsl:with-param>
+	</xsl:apply-templates>
+</xsl:if>
+</xsl:template>
+
+
+<xsl:template match="unit">	<xsl:param name="filename"/>
+	<xsl:apply-templates select="@mrp|@bldFile">
+		<xsl:with-param name="filename" select="$filename"/>
+	</xsl:apply-templates>
+</xsl:template>
+
+
+<xsl:template match="@id" mode="path">
+	<xsl:choose>
+		<xsl:when test="contains(.,':')"><xsl:value-of  select="substring-after(.,':')"/></xsl:when>
+		<xsl:otherwise><xsl:value-of  select="."/></xsl:otherwise>
+	</xsl:choose>
+</xsl:template>
+
+
+<xsl:template match="@id">
+<xsl:if test="contains(concat(' ',substring-after($all-ids,concat(' ',.,' '))),concat(' ',.,' '))">
+	<xsl:call-template name="Warning"><xsl:with-param name="text">Duplicate ID: <xsl:value-of select="name(..)"/> "<xsl:value-of select="."/>"</xsl:with-param></xsl:call-template>
+</xsl:if>
+
+<xsl:if test="contains(.,':') and not(ancestor::*/namespace::*[name()=substring-before(current(),':')])">
+	<xsl:call-template name="Error"><xsl:with-param name="text">Undefined namespace for ID "<xsl:value-of select="."/>"</xsl:with-param></xsl:call-template>
+</xsl:if>
+
+</xsl:template>
+
+
+<xsl:template match="@bldFile|@mrp"><xsl:param name="filename"/>
+
+	<xsl:variable name="fullpath"><xsl:call-template name="normpath">
+				<xsl:with-param name="path">
+					<xsl:if test="not(starts-with(.,'/'))">
+						<xsl:call-template name="before">
+							<xsl:with-param name="text" select="$filename"/>
+						</xsl:call-template>
+					</xsl:if>
+					<xsl:value-of select="."/>
+				 </xsl:with-param>
+			</xsl:call-template>
+		</xsl:variable>
+		<xsl:variable name="path">
+			<xsl:choose>
+				<xsl:when test="not(contains($filename,':'))">/<xsl:for-each select="ancestor::*/@id"><xsl:apply-templates mode="path" select="."/>/</xsl:for-each></xsl:when>
+				<xsl:otherwise><xsl:for-each select="../../../@id|../../@id"><xsl:apply-templates mode="path" select="."/>/</xsl:for-each></xsl:otherwise>
+			</xsl:choose>
+		</xsl:variable>
+		<xsl:variable name="segment">
+			<xsl:choose>
+				<xsl:when test="ancestor::layer">
+					<xsl:value-of select="concat($fullpath,'/')"/>
+				</xsl:when>
+				<xsl:when test="ancestor::package">
+					<xsl:value-of select="concat('/',substring-after(substring-after($fullpath,'/'),'/'),'/')"/>
+				</xsl:when>
+				<xsl:when test="ancestor::collection">
+					<xsl:value-of select="concat('/',substring-after(substring-after(substring-after($fullpath,'/'),'/'),'/'),'/')"/>
+				</xsl:when>
+				<xsl:otherwise>
+					<xsl:value-of select="concat('/',substring-after(substring-after(substring-after(substring-after($fullpath,'/'),'/'),'/'),'/'),'/')"/>
+				</xsl:otherwise>
+			</xsl:choose>
+		</xsl:variable>
+<xsl:choose>
+	<xsl:when test="contains($filename,':')">
+		<xsl:choose>
+			<xsl:when test="not(starts-with(.,$path) or concat(.,'/')=$path)">
+				<xsl:call-template name="Note"><xsl:with-param name="text">Unexpected <code><xsl:value-of select="name()"/></code> path for <xsl:apply-templates mode="path" select="../../../@id"/> -&gt; <strong><xsl:apply-templates mode="path" select="../../@id"/></strong> "<xsl:value-of select="."/>"</xsl:with-param></xsl:call-template>
+			</xsl:when>
+		</xsl:choose>
+	</xsl:when>
+	<xsl:otherwise>
+		<xsl:choose>
+			<xsl:when test="substring-before(substring($segment,2),'/') != substring-before(substring($path,2),'/') and (ancestor::SystemDefinition/@id-namespace!='http://www.symbian.org/system-definition' and not(contains(../../@id,':')))">
+				<xsl:call-template name="Warning"><xsl:with-param name="text">Unexpected <code><xsl:value-of select="name()"/></code> path for <xsl:apply-templates mode="path" select="../../../@id"/> -&gt; <strong><xsl:apply-templates mode="path" select="../../@id"/></strong> "<xsl:value-of select="$fullpath"/>"</xsl:with-param></xsl:call-template>
+			</xsl:when>
+			<xsl:when test="substring-before(substring($segment,2),'/') != substring-before(substring($path,2),'/')">
+				<xsl:call-template name="Error"><xsl:with-param name="text">Unexpected <code><xsl:value-of select="name()"/></code> path for <xsl:apply-templates mode="path" select="../../../@id"/> -&gt; <strong><xsl:apply-templates mode="path" select="../../@id"/></strong> "<xsl:value-of select="$fullpath"/>"</xsl:with-param></xsl:call-template>
+			</xsl:when>
+			<xsl:when test="not(starts-with($segment,$path))">
+				<xsl:call-template name="Note"><xsl:with-param name="text">Unexpected <code><xsl:value-of select="name()"/></code> path for <xsl:apply-templates mode="path" select="../../../@id"/> -&gt; <strong><xsl:apply-templates mode="path" select="../../@id"/></strong> "<xsl:value-of select="$fullpath"/>"</xsl:with-param></xsl:call-template>
+			</xsl:when>
+		</xsl:choose>
+	</xsl:otherwise>
+</xsl:choose>
+<xsl:if test="substring(.,string-length(.))='/'">
+		<xsl:call-template name="Warning"><xsl:with-param name="text"><code><xsl:value-of select="name()"/></code> path "<xsl:value-of select="."/>" should not end in /</xsl:with-param></xsl:call-template>
+</xsl:if>
+<xsl:if test="contains(.,'\')">
+		<xsl:call-template name="Error"><xsl:with-param name="text"><code><xsl:value-of select="name()"/></code> path "<xsl:value-of select="."/>" must use only forward slashes</xsl:with-param></xsl:call-template>
+</xsl:if>
+</xsl:template>
+
+
+<xsl:template match="SystemDefinition" mode="check-matches">
+	<xsl:param name="which"/>
+	<xsl:param name="other"/>
+	<xsl:for-each select="//*[@mrp]">
+		<xsl:variable name="mrp" select="@mrp"/>
+		<xsl:if test="not($other//*[@mrp=$mrp])">
+			<xsl:call-template name="Error"><xsl:with-param name="text"><xsl:value-of select="$mrp"/> has no match in <xsl:value-of select="$which"/>.</xsl:with-param></xsl:call-template>
+		</xsl:if>
+	</xsl:for-each>
+</xsl:template>
+
+<xsl:template match="*" mode="value">
+	<xsl:call-template name="Error"><xsl:with-param name="text">
+		<xsl:value-of select="name()"/>:<xsl:for-each select="@*"><xsl:value-of select="concat(name(),'=',.)"/></xsl:for-each>
+	</xsl:with-param></xsl:call-template>
+</xsl:template>
+
+<xsl:template match="*" mode="compare"><xsl:param name="base"/>
+<xsl:variable name="n" select="@id"/>
+<xsl:variable name="tag" select="name()"/>
+<xsl:variable name="v"><xsl:apply-templates select="." mode="value"/></xsl:variable>
+<xsl:variable name="v2"><xsl:apply-templates mode="value" select="$base//*[name()=$tag and @id=$n]"/></xsl:variable>
+<xsl:if  test="$v != $v2">
+	<xsl:call-template name="Error"><xsl:with-param name="text">
+		<xsl:value-of select="concat(name(),' ',@name)"/> not identical. [<xsl:value-of select="$v"/>|<xsl:value-of select="$v2"/>]</xsl:with-param></xsl:call-template>
+</xsl:if>	
+</xsl:template>
+
+
+
+<xsl:template match="unit" mode="compare" priority="1"><xsl:param name="base"/>
+<xsl:variable name="n" select="concat(@version,':',@mrp,'.',@prebuilt)"/>
+<xsl:variable name="v"><xsl:apply-templates select="." mode="value"/></xsl:variable>
+<xsl:variable name="v2"><xsl:apply-templates mode="value" select="$base//unit[concat(@version,':',@mrp,'.',@prebuilt)=$n]"/></xsl:variable>
+<xsl:if  test="$v != $v2">
+	<xsl:call-template name="Error"><xsl:with-param name="text">
+		<xsl:value-of select="concat('&#xa;',name(),' ',../@name,' v',@version)"/> not identical. [<xsl:value-of select="$v"/>|<xsl:value-of select="$v2"/>]</xsl:with-param></xsl:call-template>
+</xsl:if>
+</xsl:template>
+
+<xsl:template match="/variations/@module"> (<xsl:value-of select="."/>)</xsl:template>
+
+<xsl:template match="/variations" mode="x-check"><xsl:param name="sysdef"/>
+<xsl:call-template name="Section"><xsl:with-param name="text">vp cross-check <xsl:apply-templates select="@module"/></xsl:with-param></xsl:call-template>
+<xsl:for-each select="//component">
+	<xsl:variable name="found">
+		<xsl:apply-templates select="$sysdef" mode="lookfor">
+			<xsl:with-param name="id" select="@name"/>
+			<xsl:with-param name="version" select="@version"/>
+		</xsl:apply-templates>
+	</xsl:variable>
+	<xsl:if test="$found=''">
+		<xsl:call-template name="Error"><xsl:with-param name="text">VP component "<xsl:value-of select="@name"/>"<xsl:if test="@version"> v<xsl:value-of select="@version"/></xsl:if> not in SysDef</xsl:with-param></xsl:call-template>
+	</xsl:if>
+</xsl:for-each>
+</xsl:template>
+
+<xsl:template match="*" mode="lookfor"><xsl:param name="id"/><xsl:param name="version"/>
+	<xsl:choose>
+		<xsl:when test="string-length($version) and //component[@id=$id and unit[@version=$version]]">Found</xsl:when>
+		<xsl:when test="string-length($version)=0 and //*[@id=$id]">Found</xsl:when>
+		<xsl:otherwise>
+			<xsl:apply-templates select="document(//layer/@href | //package/@href | //collection/@href | //component/@href,.)/*/*" mode="lookfor">
+				<xsl:with-param name="version" select="$version"/>
+				<xsl:with-param name="id" select="$id"/>
+			</xsl:apply-templates>
+		</xsl:otherwise>
+	</xsl:choose>
+</xsl:template>
+
+
+
+<xsl:template match="SystemBuild" mode="x-check"><xsl:param name="sysdef"/>
+
+<xsl:call-template name="Section"><xsl:with-param name="text">System Build cross-check</xsl:with-param></xsl:call-template>
+<xsl:for-each select="//ref">
+	<xsl:variable name="found">
+		<xsl:apply-templates select="$sysdef" mode="lookfor">
+		<xsl:with-param name="id" select="current()/@item"/>
+	</xsl:apply-templates>
+</xsl:variable>
+	<xsl:if test="$found=''">
+		<xsl:call-template name="Error"><xsl:with-param name="text">Build item "<xsl:value-of select="@item"/>" not in SysDef</xsl:with-param></xsl:call-template>
+</xsl:if>
+</xsl:for-each>
+
+<xsl:for-each select="//listRef">
+	<xsl:if test="not(//list[@name=current()/@list])">
+		<xsl:call-template name="Error"><xsl:with-param name="text">Build list "<xsl:value-of select="@name"/>" not defined</xsl:with-param></xsl:call-template>
+</xsl:if>	
+</xsl:for-each>
+</xsl:template>
+
+
+<xsl:template name="my-release">
+	<xsl:variable name="n" select="@name"/>
+	<xsl:variable name="new" select="@introduced"/>
+	<xsl:variable name="end" select="@deprecated"/>
+	<xsl:choose>
+		<xsl:when test="$new!='' and $end!=''">(<xsl:value-of select="concat($new,' - ',$end)"/>)</xsl:when>
+		<xsl:when test="$new!='' ">(<xsl:value-of select="$new"/>)</xsl:when>
+		<xsl:when test="$end!=''">(? - <xsl:value-of select="$end"/>)</xsl:when>
+	</xsl:choose>
+</xsl:template>
+
+<xsl:template name="normpath"><xsl:param name="path"/>
+<!-- normalize out any ".." in the path in $path  -->
+<xsl:choose>
+	<xsl:when test="contains($path,'/../')">
+	<xsl:call-template name="normpath">
+		<xsl:with-param name="path">
+		<xsl:call-template name="before">
+			<xsl:with-param name="text" select="substring-before($path,'/../')"/>
+		</xsl:call-template>
+		<xsl:value-of select="substring-after($path,'/../')"/>
+		</xsl:with-param>
+		</xsl:call-template>
+	</xsl:when>
+	<xsl:otherwise><xsl:value-of select="$path"/></xsl:otherwise>
+</xsl:choose>
+</xsl:template>
+
+<!-- return all text before the last / -->
+<xsl:template name="before"><xsl:param name="text"/>
+<xsl:if test="contains($text,'/')">
+	<xsl:value-of select="substring-before($text,'/')"/>/<xsl:call-template name="before"><xsl:with-param name="text" select="substring-after($text,'/')"/></xsl:call-template>
+	</xsl:if>
+</xsl:template>
+
+
+</xsl:stylesheet>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysdeftools/validate/validate-sysdef.xsl	Tue Apr 06 10:25:29 2010 +0100
@@ -0,0 +1,48 @@
+<xsl:stylesheet  xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
+<!--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:
+	Validate a system definition file/files and output results as plain text
+-->
+	<xsl:output method="text"/>
+	<xsl:include href="test-model.xsl"/>
+	<xsl:param name="level" select="3"/>
+
+<xsl:template name="Section"><xsl:param name="text"/><xsl:param name="sub"/>
+<xsl:text>&#xa;&#xa;</xsl:text>
+<xsl:value-of select="$text"/>
+<xsl:if test="$sub!=''"> (<xsl:value-of select="$sub"/>)</xsl:if>
+</xsl:template>
+
+
+<xsl:template name="Note"><xsl:param name="text"/><xsl:param name="sub"/>
+<xsl:if test="$level &gt;= 3">
+<xsl:text>&#xa;Note: </xsl:text>
+<xsl:value-of select="$text"/>
+<xsl:if test="$sub!=''"> (<xsl:value-of select="$sub"/>)</xsl:if>
+</xsl:if>
+</xsl:template>
+
+<xsl:template name="Warning"><xsl:param name="text"/><xsl:param name="sub"/>
+<xsl:if test="$level &gt;= 2">
+<xsl:text>&#xa;Warning: </xsl:text>
+<xsl:value-of select="$text"/>
+<xsl:if test="$sub!=''"> (<xsl:value-of select="$sub"/>)</xsl:if>
+</xsl:if>
+</xsl:template>
+
+<xsl:template name="Error"><xsl:param name="text"/><xsl:param name="sub"/>
+<xsl:text>&#xa;Error: </xsl:text>
+<xsl:value-of select="$text"/>
+<xsl:if test="$sub!=''"> (<xsl:value-of select="$sub"/>)</xsl:if>
+</xsl:template>
+
+</xsl:stylesheet>
\ No newline at end of file
Binary file sysdeftools/xalan.jar has changed
Binary file sysdeftools/xercesImpl.jar has changed
Binary file sysdeftools/xml-apis.jar has changed