xsl-list
[Top] [All Lists]

Re: [xsl] Comparing direct ancestors

2012-05-28 15:49:39
On Mon, May 28, 2012 at 7:27 PM, Spencer Tickner
<spencertickner(_at_)gmail(_dot_)com> wrote:
Hi Ihe,

Thanks for walking though the solution as I'm sure it will help
others. Amazingly my mindset was exactly the same as yours, trying the
XPath remove and replace before tearing some hair out an moving to the
key solution proposed by David.

As with any sample code I have run into a fringe scenario that has got
me thinking of the "context" that the "use" statement,, ummm, uses.
The fringe scenario comes up with nested allowable elements:

<?xml version="1.0"?>
<root>
       <change-begin/>
       <a>
               <p>Foo<change-end/></p>
       </a>
       <change-begin/>
       <b>
               <d>
                       <t>Bar</t>
               </d>
               <d>
                       <t>Foo <p>This</p> whatever</t>
               </d>
       </b>
       <change-end/>
       <p>Nothing <change-begin/>to worry<change-end/> about</p>
<!-- Fringe scenario -->
       <b>
               <d>
                       <t><change-begin/>This <p>and</p> <t>That</t> and 
<p>that and </p> a</t>
               </d>
       </b>
       <change-end/>
</root>

In the last case the key puts the <change-end/> in the wrong spot


Well first up I have to own up to an oversight- that meant that my
change-begins and change-ends both came at the start of the allowable
elements.

To fix it up the key added in step five needs to have a different name
(I followed the established convention of cb and ce) and the template
in step 4 now sandwiches the apply-templates between the copy-of's for
change-begin and change-end (code below).

As for skipping nested p|t, are you sure you will not have a scenario
where you will not have nested changes?


<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"; version="2.0"
                exclude-result-prefixes="">

    <!-- STEP THREE Define a key to pair up a change to the allowable
element it should go into -->
    <xsl:key name="cb" match="*[not (self::p or self::t)]/change-begin"
            use="generate-id(following::*[self::p or self::t][1])"/>

    <!-- STEP FIVE By symmetry extend the key to pair up change-ends
to allowable elements -->
    <xsl:key name="ce" match="*[not (self::p or self::t)]/change-end"
            use="generate-id(preceding::*[self::p or self::t]
   [1])"/>

   <xsl:template match="@*|node()">
      <xsl:copy>
        <xsl:apply-templates select="@*|node()"/>
      </xsl:copy>
   </xsl:template>

   <!-- STEP ONE Remove all change-begin and change-end elements -->
    <xsl:template match="change-begin|change-end"/>

    <!-- STEP TWO Restore all change-begin and change-ends that are
already in the correct place -->
    <xsl:template
match="p/change-begin|p/change-end|t/change-begin|t/change-end">
       <xsl:copy-of select="."/>
    </xsl:template>

    <!-- STEP FOUR USE the key in STEP THREE to insert the
change-begin's in the right place -->
    <xsl:template match="p|t">
            <xsl:copy>
                 <xsl:copy-of select="key('cb', generate-id())"/>
                <xsl:apply-templates/>
                <xsl:copy-of select="key('ce', generate-id())"/>
            </xsl:copy>
    </xsl:template>


</xsl:stylesheet>

--~------------------------------------------------------------------
XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list
To unsubscribe, go to: http://lists.mulberrytech.com/xsl-list/
or e-mail: <mailto:xsl-list-unsubscribe(_at_)lists(_dot_)mulberrytech(_dot_)com>
--~--