Re: [xsl] RE : Re: [xsl] Merging attributes in one XML file with node values in another (identical structure)

Subject: Re: [xsl] RE : Re: [xsl] Merging attributes in one XML file with node values in another (identical structure)
From: "Dimitre Novatchev" <dnovatchev@xxxxxxxxx>
Date: Fri, 23 Jun 2006 06:01:33 -0700
On 6/23/06, Florent Georges <darkman_spam@xxxxxxxx> wrote:

Interesting. But I can't see what zipTrees() is expected to do exactly. Could you please explain it a bit further (for example a simple pseudo-algorithm)? And what is the role of $zipnodeFun and $ziparcFun? BTW "arc" is the French word for "edge" in the graph theory, but I'm not sure it is relevant here.




This will be analogous to the way foldl-tree() is specified at present
in FXSL. Here is its code:

<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
xmlns:f="http://fxsl.sf.net/";
exclude-result-prefixes="f"

   <xsl:template name="foldl-tree">
     <xsl:param name="pFuncNode" select="/.."/>
     <xsl:param name="pFuncSubtrees" select="/.."/>
     <xsl:param name="pA0"/>
     <xsl:param name="pNode" select="/.."/>

     <xsl:choose>
        <xsl:when test="not($pNode)">
           <xsl:copy-of select="$pA0"/>
        </xsl:when>
        <xsl:otherwise>

<xsl:variable name="vSubtrees" select="$pNode/*"/>

           <xsl:variable name="vSubTreeResult">
             <xsl:call-template name="foldl-tree_">
	 <xsl:with-param name="pFuncNode" select="$pFuncNode"/>
	 <xsl:with-param name="pFuncSubtrees" select="$pFuncSubtrees"/>
	 <xsl:with-param name="pA0" select="$pA0"/>
	 <xsl:with-param name="pSubTrees" select="$vSubtrees"/>
             </xsl:call-template>
           </xsl:variable>

           <xsl:apply-templates select="$pFuncNode[1]" mode="f:FXSL">
             <xsl:with-param name="arg0" select="$pFuncNode[2]"/>
             <xsl:with-param name="arg1" select="$pNode/@tree-nodeLabel"/>
             <xsl:with-param name="arg2" select="$vSubTreeResult"/>
           </xsl:apply-templates>

        </xsl:otherwise>
     </xsl:choose>
   </xsl:template>

   <xsl:template name="foldl-tree_">
     <xsl:param name="pFuncNode" select="/.."/>
     <xsl:param name="pFuncSubtrees" select="/.."/>
     <xsl:param name="pA0"/>
     <xsl:param name="pSubTrees" select="/.."/>

     <xsl:choose>
        <xsl:when test="not($pSubTrees)">
           <xsl:copy-of select="$pA0"/>
        </xsl:when>
        <xsl:otherwise>
	      <xsl:variable name="vSubTree1Result">
	        <xsl:call-template name="foldl-tree">
	           <xsl:with-param name="pFuncNode" select="$pFuncNode"/>
	           <xsl:with-param name="pFuncSubtrees" select="$pFuncSubtrees"/>
	           <xsl:with-param name="pA0" select="$pA0"/>
	           <xsl:with-param name="pNode" select="$pSubTrees[1]"/>
	        </xsl:call-template>
	      </xsl:variable>
	
	      <xsl:variable name="vRestSubtreesResult">
	        <xsl:call-template name="foldl-tree_">
	           <xsl:with-param name="pFuncNode" select="$pFuncNode"/>
	           <xsl:with-param name="pFuncSubtrees" select="$pFuncSubtrees"/>
	           <xsl:with-param name="pA0" select="$pA0"/>
	           <xsl:with-param name="pSubTrees"
select="$pSubTrees[position() > 1]"/>
	        </xsl:call-template>
	      </xsl:variable>
	
	        <xsl:apply-templates select="$pFuncSubtrees" mode="f:FXSL">
                             <xsl:with-param name="arg1"
select="$vSubTree1Result"/>
                             <xsl:with-param name="arg2"
select="$vRestSubtreesResult"/>
	        </xsl:apply-templates>
       </xsl:otherwise>
     </xsl:choose>
   </xsl:template>

</xsl:stylesheet>


It is similar to the way foldl() operates on a list, but a tree is two-dimensional. It has nodes and every node has a set of subnodes (subtrees).

This is why, two functions are needed here as parameters -- not just
one function as in the linear foldl() case. One of these functions
operater on the root node of the tree. The second function operates on
all subnodes (subtrees) of the root node.

The test that comes with FXSL is one of the simplest possible. It
computes the sum of all "tree-nodeLabel" attributes of all nodes in a
tree:

testFoldl-tree.xsl:
=============

<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
xmlns:f="http://fxsl.sf.net/";
xmlns:add-tree="add-tree"
exclude-result-prefixes="f add-tree"

<xsl:import href="../f/foldl-tree.xsl"/>

  <!-- This transformation must be applied to:
       numTree.xml
   -->

<add-tree:add-tree/>

<xsl:output method="text"/>

   <xsl:template match="/">
     <xsl:variable name="vAdd" select="document('')/*/add-tree:*[1]"/>

     <xsl:call-template name="foldl-tree">
	    <xsl:with-param name="pFuncNode" select="$vAdd"/>
	    <xsl:with-param name="pFuncSubtrees" select="$vAdd"/>
	    <xsl:with-param name="pA0" select="0"/>
	    <xsl:with-param name="pNode" select="/*"/>
     </xsl:call-template>
   </xsl:template>

   <xsl:template match="*[namespace-uri()='add-tree']"
    mode="f:FXSL">
     <xsl:param name="arg1"/>
     <xsl:param name="arg2"/>

     <xsl:value-of select="$arg1 + $arg2"/>
   </xsl:template>

</xsl:stylesheet>

Both function passed are the same "add" function.

When the above xslt stylesheet is applied on this xml document:

<nums tree-nodeLabel="01">
 <num tree-nodeLabel="02">01</num>
 <num tree-nodeLabel="03">02</num>
 <num tree-nodeLabel="04">03</num>
 <num tree-nodeLabel="05">04</num>
 <num tree-nodeLabel="06">05</num>
 <num tree-nodeLabel="07">06</num>
 <num tree-nodeLabel="08">07</num>
 <num tree-nodeLabel="09">08</num>
 <num tree-nodeLabel="10">09</num>
 <num tree-nodeLabel="11">10</num>
</nums>

the correct result: 66 is produced.

The zipTrees() will be specified in a similar way. When I have free
time I will play with adding this function to FXSL.


-- Cheers, Dimitre Novatchev --------------------------------------- Truly great madness cannot be achieved without significant intelligence.

Current Thread