[xsl] Remove Duplicates from Recursive Template Calls

Subject: [xsl] Remove Duplicates from Recursive Template Calls
From: "Patrick Lademan" <plademan@xxxxxxxxxxxxxxxxx>
Date: Tue, 03 May 2005 08:48:14 -0500
Hello,

I'm trying to use XALAN/XSL on my XML system design document to create a
development time estimate, but I can't remove the duplicate shared components
from the build list.  In the sample output below, I was able to recursively
display all components needed but the common components keep reappearing.  For
example, I need SelectBox to be listed the first time it appears only, because
once it's built we do not need to spend the time to build it again.  Also note
that the Phase 2 deliverables should only list the "SchedulingReport" because
the subcomponents were already built in Phase1.

I can't use the ".=preceding" because I'm using recursive template calls.
I've tried creating a global variable containing all processed components, but
global variables in XSL behave like global constants.  I tried to find a way
to set an attribute in the source document to indicate that the component has
been processed, but I can not find a method to do that.  I tried to flag the
processed nodes, but I can't find a method to do that either.

Is there a method to remove the duplicated shared components when recursing to
unknown depths?
  or
Is there a completely different way to solve this problem?

----- Sample Output -----
Deliverables: Phase1
(6) AllocationReport
     (4) Markets
         (1) Market
             (6) SelectBox
     (4) ModelYear
         (6) SelectBox
(6) CheckOut
     (1) Market
         (6) SelectBox

Deliverables: Phase2
(6) SchedulingReport
     (1) Market
         (6) SelectBox
     (4) ModelYear
         (6) SelectBox

----- Sample Document -----
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE project SYSTEM "Deliverables.dtd" >
<project>
    <componentGroup type="Screen">
        <category name="Edit">
            <component id="CheckOut" estimate="6">
                <componentReference idRef="Market" />
            </component>
        </category>
        <category name="Reports">
            <component id="AllocationReport" estimate="6">
                <componentReference idRef="Markets" />
                <componentReference idRef="ModelYear" />
            </component>
            <component id="SchedulingReport" estimate="6">
                <componentReference idRef="Market" />
                <componentReference idRef="ModelYear" />
            </component>
        </category>
    </componentGroup>
    <componentGroup type="Control">
        <component id="SelectBox" estimate="6">
        </component>
        <component id="Market" estimate="1">
            <componentReference idRef="SelectBox"/>
        </component>
        <component id="Markets" estimate="4">
            <componentReference idRef="Market"/>
        </component>
        <component id="ModelYear" estimate="4">
            <componentReference idRef="SelectBox"/>
        </component>
    </componentGroup>
    <componentGroup type="Deliverable">
        <component id="Phase1">
            <componentReference idRef="CheckOut"/>
            <componentReference idRef="AllocationReport"/>
        </component>
        <component id="Phase2">
            <componentReference idRef="SchedulingReport"/>
        </component>
    </componentGroup>
</project>

----- Sample Stylesheet -----
<?xml version="1.0"?>
<xsl:stylesheet
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
  xmlns:xalan="http://xml.apache.org/xslt";
  version="1.0" >
<xsl:output method="html" encoding="UTF-8" indent="yes"
xalan:indent-amount="2" />
<xsl:template match="/project">
  <xsl:call-template name="Deliverables" />
</xsl:template>
<xsl:template name="Deliverables">
  <xsl:for-each select="/project/componentGroup">
  <xsl:if test="@type='Deliverable'">
    <xsl:for-each select="component">
      Deliverables: <xsl:value-of select="@id"/><br/>
      <xsl:call-template name="DeliverableReferences"/>
      <br/>
    </xsl:for-each>
  </xsl:if>
  </xsl:for-each>
</xsl:template>
<xsl:template name="DeliverableReferences">
  <xsl:param name="indent" select="''"/>
  <xsl:for-each select="componentReference">
  <xsl:sort select="@idRef" />
  <xsl:variable name="idRef" select="@idRef" />
      <xsl:for-each select="//component/@id[.=$idRef]//..">
          <xsl:value-of select="$indent"/>
          (<xsl:value-of select="@estimate"/>)
          <xsl:value-of select="@id"/>
          <br/>
          <xsl:call-template name="DeliverableReferences">
              <xsl:with-param name="indent"
select="concat($indent,'&#160;&#160;&#160;&#160;')"/>
          </xsl:call-template>
      </xsl:for-each>
  </xsl:for-each>
</xsl:template>
</xsl:stylesheet>

Thank you in advance for any insights that you can provide,

Pat
--
___________________________________________________________
Sign-up for Ads Free at Mail.com
http://promo.mail.com/adsfreejump.htm

Current Thread