Re: How to remove duplicates nodes?

Subject: Re: How to remove duplicates nodes?
From: Joel Riedesel <jriedese@xxxxxxxxx>
Date: Sat, 26 Aug 2000 06:20:58 -0600
This looks nice, but it's actually a bit more complex than that.
You've provided some general guidelines which I think I can work
with when I tackle this again.

The additional complexity comes from what a Context really is.
It is a list of ObjectReference elements (a kind of path, if you will).
And it is not a valid assumption that the @objectID of an ObjectReference
is the unique element of a Context (unfortunately).

The only way to compute a unique value of a Context (almost a 
hashcode if you will) is by looking at all the ObjectReference
elements of the Context and concatenating all their attributes
together (perhaps by including spaces):  @objectID, @attributeGroupID,
@instanceID, and @attributeID.

By computing that correct unique hash for a context, I can then continue
along with the pattern you provided here to remove duplicates
using the Muenchian Method (which I had studied before I sent
my node - but I didn't think of these more complex key generation
methods - thanks!).

Your help is much appreciated, thanks a bunch.

Joel

Jeni Tennison wrote:
> 
> Joel,
> 
> >I don't believe I can use the 'key' trick since the Context element
> >is throughout my XML and I only want to do this duplicate analysis
> >from within a particular rule mapping element.
> 
> This does add an extra factor into using the Muenchian Method for getting
> unique nodes.  [This email assumes familiarity with the general method -
> look at http://www.jenitennison.com/xslt/grouping/ for more details.]
> There are two ways that you can do it.
> 
> The first is to declare the key in the normal way: you're interested in
> Context elements, and the unique thing about the Context element is (I
> think?) the @objectID of the ObjectReference that it holds:
> 
> <xsl:key name="contexts" match="Context" use="ObjectReference/@objectID" />
> 
> This means that with key('contexts', $objectID) you will get all the
> Contexts in the source that have that particular ObjectReference/@objectID.
>  If you know what RuleMapping you're interested in, you can filter those
> nodes in terms of that RuleMapping.  So, within a template matching
> RuleMapping elements, if you set a variable to hold the id of the RuleMapping:
> 
> <xsl:variable name="rule-mapping" select="@id" />
> 
> You can then filter the Contexts returned by the key (using a predicate) to
> give only those Contexts that have that RuleMapping as an ancestor:
> 
>   key('contexts', $objectID)[ancestor::RuleMapping[@id = $rule-mapping]]
> 
> So this XPath will give all the Contexts within that particular RuleMapping
> that have that particular ObjectReference/@objectID.  Slotting that in to
> the usual Muenchian solution, you get:
> 
> <xsl:template match="RuleMapping">
>   <xsl:variable name="rule-mapping" select="@id" />
>   Rule Mapping: <xsl:value-of select="@name" />
>   Unique Contexts:
>   <xsl:copy-of
>     select="Rule/RHS/Context[generate-id() = generate-id(key('contexts',
> ObjectReference/@objectID)[ancestor::RuleMapping[@id =
> $rule-mapping]][1])]" />
> </xsl:template>
> 
> Filtering the results of the key() function to get only those returned by
> it that meet a certain criteria, is a good general solution.  It's
> especially useful when you want a dynamic way of filtering the results of
> the key, such as a keyword passed in as a parameter.
> 
> The second method, which may be better in your case, is to create a key
> with key values that hold information both about the
> ObjectReference/@objectID *and* about the RuleMapping that the Context is
> within.  You can do this by concatenating the two pieces of information
> (with an appropriate separator) to give the key value:
> 
> <xsl:key name="contexts" match="Context"
>    use="concat(ancestor::RuleMapping/@id, '::', ObjectReference/@objectID)" />
> 
> You can then index into the key using a value constructed in the same way,
> giving the template:
> 
> <xsl:template match="RuleMapping">
>   <xsl:variable name="rule-mapping" select="@id" />
>   Rule Mapping: <xsl:value-of select="@name" />
>   Unique Contexts:
>   <xsl:copy-of
>     select="Rule/RHS/Context[generate-id() = generate-id(key('contexts',
> concat($rule-mapping, '::', ObjectReference/@objectID))[1])]" />
> </xsl:template>
> 
> Both of these methods give the results that you're after in both SAXON and
> Xalan.
> 
> I hope that this helps,
> 
> Jeni
> 
> Jeni Tennison
> http://www.jenitennison.com/

-- 
Joel Riedesel
Jnana Technologies Corporation
mailto:jriedese@xxxxxxxxx


 XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list


Current Thread