This is the mail archive of the
xsl-list@mulberrytech.com
mailing list .
Re: How to remove duplicates nodes?
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@jnana.com
XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list