[xsl] Re: Complex merge of two documents at multiple levels

Subject: [xsl] Re: Complex merge of two documents at multiple levels
From: "Mark Peters" <flickrmeister@xxxxxxxxx>
Date: Fri, 7 Nov 2008 08:44:36 -0500
Hi Everyone,

I'm trying to merge two documents and apply logic for the merge at
multiple levels. Lots of information for document merges is available
in the archives for this list (thanks!). I've been able to combine the
two documents and merge nodes at the secondary level. But I'm not sure
how to begin to apply additional logic at the tertiary levels.

Here are my two XML files:

File 1 (F1)

<a>
    <b name="1">
        <c1>Text string</c1>
        <c2 id="c2.1">
            <d>Text string</d>
        </c2>
        <c2 id="c2.2">
            <d/>
        </c2>
        <c2 id="c2.3">
            <d>Text string</d>
        </c2>
        <c2 id="c2.4">
            <d/>
        </c2>
        <c2 id="c2.5">
            <d/>
        </c2>
        <c2 id="c2.6">
            <d/>
        </c2>
    </b>
    <b name="2">
        <c1/>
        <c2 id="c2.7">
            <d/>
        </c2>
        <c2 id="c2.8">
            <d/>
        </c2>
        <c2 id="c2.9">
            <d/>
        </c2>
        <c2 id="c2.10">
            <d>Text string</d>
        </c2>
        <c2 id="c2.11">
            <d/>
        </c2>
        <c2 id="c2.12">
            <d/>
        </c2>
    </b>
</a>


File 2 (F2)

<a>
    <b name="1">
        <c1/>
        <c2 id="c2.1">
            <d></d>
        </c2>
        <c2 id="c2.2">
            <d/>
        </c2>
        <c2 id="c2.3">
            <d></d>
        </c2>
        <c2 id="c2.4">
            <d/>
        </c2>
        <c2 id="c2.5">
            <d/>
        </c2>
        <c2 id="c2.6">
            <d/>
        </c2>
        <c2 id="c2.6a">
            <d/>
        </c2>
        <c2 id="c2.6b">
            <d/>
        </c2>
    </b>
    <b name="2">
        <c1/>
        <c2 id="c2.7">
            <d/>
        </c2>
        <c2 id="c2.8">
            <d/>
        </c2>
        <c2 id="c2.9">
            <d/>
        </c2>
        <c2 id="c2.10">
            <d></d>
        </c2>
        <c2 id="c2.11">
            <d/>
        </c2>
        <c2 id="c2.12">
            <d/>
        </c2>
    </b>
    <b name="3">
        <c1/>
        <c2 id="c2.13">
            <d/>
        </c2>
        <c2 id="c2.14">
            <d/>
        </c2>
        <c2 id="c2.15">
            <d/>
        </c2>
        <c2 id="c2.16">
            <d/>
        </c2>
        <c2 id="c2.17">
            <d/>
        </c2>
        <c2 id="c2.18">
            <d/>
        </c2>
    </b>
</a>

My objectives are as follows:

Combine all of the b nodes.
Replace the f2.c1 nodes with their f1.c1 counterparts
Combine the c1 nodes. Where there are duplicates, replace the f2.c1
nodes with their f1.c1 counterparts
Replace the f2.d1 nodes with their f1.d1 counterparts

Here is the desired result:

<a>
    <b name="1">
        <c1>Text string</c1>
        <c2 id="c2.1">
            <d>Text string</d>
        </c2>
        <c2 id="c2.2">
            <d/>
        </c2>
        <c2 id="c2.3">
            <d>Text string</d>
        </c2>
        <c2 id="c2.4">
            <d/>
        </c2>
        <c2 id="c2.5">
            <d/>
        </c2>
        <c2 id="c2.6">
            <d/>
        </c2>
        <c2 id="c2.6a">
            <d/>
        </c2>
        <c2 id="c2.6b">
            <d/>
        </c2>
    </b>
    <b name="2">
        <c1/>
        <c2 id="c2.7">
            <d/>
        </c2>
        <c2 id="c2.8">
            <d/>
        </c2>
        <c2 id="c2.9">
            <d/>
        </c2>
        <c2 id="c2.10">
            <d>Text string</d>
        </c2>
        <c2 id="c2.11">
            <d/>
        </c2>
        <c2 id="c2.12">
            <d/>
        </c2>
    </b>
    <b name="3">
        <c1/>
        <c2 id="c2.13">
            <d/>
        </c2>
        <c2 id="c2.14">
            <d/>
        </c2>
        <c2 id="c2.15">
            <d/>
        </c2>
        <c2 id="c2.16">
            <d/>
        </c2>
        <c2 id="c2.17">
            <d/>
        </c2>
        <c2 id="c2.18">
            <d/>
        </c2>
    </b>
</a>


Here is the XSL I'm currently using. This transformation fulfills
Objective 1, but does not take into account the other objectives.

<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
xmlns:exslt="http://exslt.org/common";>
       <xsl:output indent="yes"/>
       <xsl:template match="/">
               <xsl:variable name="temp">
                       <a>
                               <xsl:copy-of select="document(/files/file)/a/b"/>
                       </a>
               </xsl:variable>
               <a>
                       <xsl:for-each
select="exslt:node-set($temp)/a/b[generate-id()=generate-id(key('c',@name))]">
                               <xsl:sort select="@name"/>
                               <xsl:copy>
                                     <xsl:copy-of select="@*|key('c',@name)/*"/>
                               </xsl:copy>
                      </xsl:for-each>
               </a>
       </xsl:template>
       <xsl:key name="c" match="b" use="@name"/>
</xsl:stylesheet>


What mechanism could I use to compare the elements nested within each
merged b node?

Thanks,
Mark

--

Mark Peters
Senior Technical Writer
Saba Software

Current Thread