Re: [xsl] How to make this XSLT elimination transformation works exclusively for different node parents?

Subject: Re: [xsl] How to make this XSLT elimination transformation works exclusively for different node parents?
From: Wendell Piez <wapiez@xxxxxxxxxxxxxxxx>
Date: Fri, 08 Jun 2012 12:30:14 -0400
Jo,

You could extend your XPath to restrict the comparison to the same nodeA ancestor like this -- instead of

deep-equal(.,preceding::*[name()=current()/name()][@id=current()/@id][1])

say

deep-equal(.,ancestor::nodeA//*[ ... ][ ... ][. &lt;&lt; current()][1]

(Untested.)

But the logic is complex enough here that I would be tempted to refactor into a function. Something like

<xsl:function name="d:duplicate" as="xs:boolean">
  <xsl:param name="i" as="element()">
  <!-- Given a node, return true() iff another node exists
       inside a nodeA ancestor with the same name and @id,
       but before this one, with the same value -->
  <xsl:sequence select="exists(
    $i/ancestor::nodeA//*
        [name()=name($i)]
        [@id=$i/@id]
        [. &lt;&lt; $i]
        [deep-equal(.,$i)])"/>
</xsl:function>

Then

<xsl:match="*[d:duplicate(.)]"/>

Note: untested.

This also exposes what might be a bug in your logic. If you toss only nodes that have the same content as the first node with the same name and @id, you will allow duplicates that appear after the first. (That is, as long as the second and third are not the same as the first, they will both be kept, even if the third is the same as the second.)

If you mean to keep such duplicates, the function would have to be adjusted.

Cheers,
Wendell

On 6/8/2012 2:43 AM, Jo Na wrote:
Hi,
I have this input:

<myroot>
     <nodeA id="a">
         <section id="i">
             <item1 id="0" method="create">
                 <somechild>a</somechild>
             </item1>

             <item1 id="1" method="create">
                 <otherchild>a</otherchild>
             </item1>
         </section>

         <section id="i">
             <item1 id="0" method="create">  <!-- second consecutive
create, we remove this -->
                 <somechild>a</somechild>
             </item1>
             <item1 id="0" method="create">  <!-- third consecutive
create, BUT children have different value , so we don't remove this
-->
                 <somechild>bbb</somechild>
             </item1>
             <item1 id="3" method="create">
                 <other>xx</other>
             </item1>

             <item1 id="0" method="change">
                 <otherchild>a</otherchild>
             </item1>
             <item1 id="0" method="change">  <!-- second consecutive
create, we remove this -->
                 <otherchild>a</otherchild>
             </item1>
         </section>
     </nodeA>
</myroot>

and this is my xslt 2.0:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform";>
    <xsl:output indent="yes"/>
    <xsl:strip-space elements="*"/>

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

    <xsl:template
match="*[*][deep-equal(.,preceding::*[name()=current()/name()][@id=current()/@id][1])]"/>
</xsl:stylesheet>

How to make that works for multiple nodeA with different id? Right now
my XSLT only works for 1 nodeA.
The objective is to remove successive duplicate with the same element
name item1 item2 etc, same id and same method.
This is what the multiple nodeA input and the expected output:
<myroot>
     <nodeA id="a">
         <section id="i">
             <item1 id="0" method="create">
                 <somechild>a</somechild>
             </item1>

             <item1 id="1" method="create">
                 <otherchild>a</otherchild>
             </item1>
         </section>

         <section id="i">
             <item1 id="0" method="create">  <!-- third consecutive
create, BUT children have different value , so we don't remove this
-->
                 <somechild>bbb</somechild>
             </item1>
             <item1 id="3" method="create">
                 <other>xx</other>
             </item1>

             <item1 id="0" method="change">
                 <otherchild>a</otherchild>
             </item1>
         </section>
     </nodeA>

         <nodeA id="b">
         <section id="i">
             <item1 id="0" method="create">
                 <somechild>a</somechild>
             </item1>

             <item1 id="1" method="create">
                 <otherchild>a</otherchild>
             </item1>
         </section>

         <section id="i">
             <item1 id="0" method="create">  <!-- third consecutive
create, BUT children have different value , so we don't remove this
-->
                 <somechild>bbb</somechild>
             </item1>
             <item1 id="3" method="create">
                 <other>xx</other>
             </item1>

             <item1 id="0" method="change">
                 <otherchild>a</otherchild>
             </item1>
         </section>
     </nodeA>
</myroot>

Expected Output:

<myroot>
     <nodeA id="a">
         <section id="i">
             <item1 id="0" method="create">
                 <somechild>a</somechild>
             </item1>

             <item1 id="1" method="create">
                 <otherchild>a</otherchild>
             </item1>
         </section>

         <section id="i">
             <item1 id="0" method="create">  <!-- third consecutive
create, BUT children have different value , so we don't remove this
-->
                 <somechild>bbb</somechild>
             </item1>
             <item1 id="3" method="create">
                 <other>xx</other>
             </item1>

             <item1 id="0" method="change">
                 <otherchild>a</otherchild>
             </item1>
         </section>
     </nodeA>

     <nodeA id="b">
         <section id="i">
             <item1 id="0" method="create">
                 <somechild>a</somechild>
             </item1>

             <item1 id="1" method="create">
                 <otherchild>a</otherchild>
             </item1>
         </section>

         <section id="i">
             <item1 id="0" method="create">  <!-- third consecutive
create, BUT children have different value , so we don't remove this
-->
                 <somechild>bbb</somechild>
             </item1>
             <item1 id="3" method="create">
                 <other>xx</other>
             </item1>

             <item1 id="0" method="change">
                 <otherchild>a</otherchild>
             </item1>
         </section>
     </nodeA>
</myroot>



Thanks very much.



-- ====================================================================== Wendell Piez mailto:wapiez@xxxxxxxxxxxxxxxx Mulberry Technologies, Inc. http://www.mulberrytech.com 17 West Jefferson Street Direct Phone: 301/315-9635 Suite 207 Phone: 301/315-9631 Rockville, MD 20850 Fax: 301/315-8285 ---------------------------------------------------------------------- Mulberry Technologies: A Consultancy Specializing in SGML and XML ======================================================================

Current Thread