I cannot understand either the problem or the solutions.
Sorry, i was probably not clear.
You are speaking about "trees", but you are using your $tree variable just
as a node-set (tree with a depth of one).
It contains the document() loaded.
Probably if you describe your problem here, many people will be able to
help.
Would be happy if such solution existed. I've been searching for a while.
We have a main xml file containing a recursive structure:
<definition id="first" ... >
<param name="p1">value1</param>
<param name="p2">value2</param>
<section name="s1">
<param name="p3">value3</param>
<param name="p4">value4</param>
</section>
<children>
<definition id="second" ...>
</definition>
<include id="overridden-id" definition="myfile">
<param name="p5">value5</param>
<section name="s2">
<param name="p6">value6</param>
</section>
<children>
<definition id="ignored" .../>
</children>
</include>
</children>
</definition>
The included 'myfile' contains itself a definition:
<definition id="included" other-attrib="foo">
<param name="p5">overridden value5</param>
<section name="s2">
<param name="p7">value7</param>
</section>
<children>
<definition id="included-too" .../>
</children>
</definition>
The purpose is to include the file(s) and override the elems/attribs with
the values contained in <include> elems, _only_ for some elemes/attribs
that are authorized to be overriden
Here is the wished result for the example here:
<definition id="first" ... >
<param name="p1">value1</param>
<param name="p2">value2</param>
<section name="s1">
<param name="p3">value3</param>
<param name="p4">value4</param>
</section>
<children>
<definition id="second" ...>
</definition>
<definition id="overridden-id" other-attrib="foo">
<param name="p5">overridden value5</param>
<section name="s2">
<param name="p6">value6</param>
<param name="p7">value7</param>
</section>
<children>
<definition id="included-too" .../>
</children>
</definition>
</children>
</definition>
Note that include/children are ignored because children cannot be
overridden.
The included file can contain other include elements too.
One more constraint: our xml format can be extended with other ns and the
xsl sheet should be easily extendable (ie by adding only a template that
could be included if possible).
My solution (?) currently is (sorry for the length):
(not working completely
<xsl:template match="/">
<xsl:apply-templates />
</xsl:template>
<!-- ::: start to merge on include only ::: -->
<xsl:template match="include">
<!-- try to retrieve the included ndf -->
<xsl
aram name="ndf" select="@definition" />
<xsl:call-template name="merge-trees">
<xsl:with-param name="included-ndf" select="document($ndf)/definition" />
<xsl:with-param name="main-ndf" select="." />
</xsl:call-template>
</xsl:template>
<!-- ::: merge two trees, some elements and attribs can be overridden ::: -->
<xsl:template name="merge-trees">
<xsl
aram name="included-ndf" />
<xsl
aram name="main-ndf" />
<xsl:choose>
<!-- loop recursively on included elements -->
<xsl:when test="count($included-ndf)>0">
<xsl:variable name="included-elt" select="$included-ndf[1]" />
<!-- find overriding element from main -->
<xsl:variable name="main-elt">
<xsl:apply-templates select="$main-ndf" mode="find-elem-in-main">
<xsl:with-param name="ie" select="$included-elt" />
</xsl:apply-templates>
</xsl:variable>
<xsl:choose>
<!-- handle overriding (if any) -->
<xsl:when test="boolean($main-elt)">
<xsl:apply-templates select="exslt:node-set($main-elt)"
mode="mix-with-main">
<xsl:with-param name="ie" select="$included-elt" />
</xsl:apply-templates>
<!-- recurse on following -->
<!-- commented because leads to infinite loop
xsl:call-template name="merge-trees">
<xsl:with-param name="included-ndf"
select="$included-ndf[position() > 1]" />
<xsl:with-param name="main-ndf"
select="$main-ndf[generate-id() !=
generate-id(exslt:node-set($main-elt))]" />
</xsl:call-template-->
</xsl:when>
<!-- else simply copy current included element -->
<xsl
therwise>
<xsl:apply-templates select="." />
</xsl
therwise>
</xsl:choose>
</xsl:when>
<!-- copy remaining main elements -->
<xsl
therwise>
<xsl:apply-templates select="$main-ndf" />
</xsl
therwise>
</xsl:choose>
</xsl:template>
<!-- ::::::::::: extendable part ::::::::::::
(we can include similar templates later) -->
<!-- ::: find the element in main that could override $ie (included element) ::: -->
<xsl:template match="include" mode="find-elem-in-main">
<xsl
aram name="ie" />
<xsl:if test="name($ie)='definition'">
<xsl:copy-of select="." />
</xsl:if>
</xsl:template>
<xsl:template match="param" mode="find-elem-in-main">
<xsl
aram name="ie" />
<xsl:if test="name($ie)='param' and $ie/@name = @name">
<xsl:copy-of select="." />
</xsl:if>
</xsl:template>
<!-- ::: merge included element with overriding in main ::: -->
<xsl:template match="include" mode="mix-with-main">
<xsl
aram name="ie" />
<xsl:element name="definition">
<xsl:attribute name="id">
<xsl:choose>
<xsl:when test="boolean(@id)">
<xsl:value-of select="@id" />
</xsl:when>
<xsl:when test="boolean($ie/@id)">
<xsl:value-of select="$ie/@id" />
</xsl:when>
<xsl
therwise>
<xsl:text>undefined</xsl:text>
</xsl
therwise>
</xsl:choose>
</xsl:attribute>
<xsl:apply-templates select="$ie/@*[name()!='definition' and name()!='id']" />
<xsl:apply-templates select="@*[name()!='definition' and name()!='id']" />
<!-- recurse on children -->
<xsl:call-template name="merge-trees">
<xsl:with-param name="included-ndf" select="$ie/*" />
<xsl:with-param name="main-ndf" select="./*" />
</xsl:call-template>
</xsl:element>
</xsl:template>
<xsl:template match="param" mode="mix-with-main">
<xsl
aram name="ie" />
<xsl:copy>
<xsl:apply-templates select="$ie" />
</xsl:copy>
</xsl:template>
<!-- /::::::::::: extendable part :::::::::::: -->
<!-- ::: copy all others and don't forget attributes ::: -->
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*" />
</xsl:copy>
</xsl:template>