Subject: Re: How to remove duplicates nodes? From: Jeni Tennison <mail@xxxxxxxxxxxxxxxx> Date: Sat, 26 Aug 2000 14:04:02 +0100 |
Joel, >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. Hmm. It isn't easy within XPath to work with strings where you don't know how long they are - you have to use recursion to parse them or create them, which means using named templates. But you can't call named templates from within the 'use' attribute of xsl:key, which means that you're fairly limited with the keys that you can put together, unless you start getting into extension functions. Do you have the freedom to change the XML source format? From the description of the underlying data that you've given here, it would perhaps make more sense to have uniquely identified contexts: <Context id="532"> <ObjectReference objectID="152" attributeGroupID="153" instanceID="0" attributeID="154"/> </Context> and ContextReferences to them: <ContextReference contextID="532" /> in the same way as you have ObjectReferences. If you can't, then the solution will involve a mode that creates a unique identifier for the Context: <xsl:template match="Context" mode="generate-id"> <xsl:for-each select="ObjectReference"> <xsl:for-each select="@*"> <xsl:value-of select="." /> <xsl:if test="position() != last()">,</xsl:if> </xsl:for-each> <xsl:if test="position() != last()">;</xsl:if> </xsl:for-each> </xsl:template> You then have to go through each of the Contexts to see if it is unique. Checking whether it's unique involves checking each of the preceding Contexts within the RuleMapping to see if any of them have the same generated id as the current one. Because the generated id is being done through a template, you can't use XPath for this, you have to do it by hand. <xsl:template match="RuleMapping"> Rule Mapping: <xsl:value-of select="@name" /> <xsl:for-each select="Rule/RHS/Context"> <xsl:variable name="this-context-position" select="position()" /> <xsl:variable name="this-context-id"> <xsl:apply-templates select="." mode="generate-id" /> </xsl:variable> <xsl:variable name="preceding"> <xsl:for-each select="ancestor::RuleMapping/Rule/RHS/Context[following::Context[generate-i d() = generate-id(current())]]"> <xsl:variable name="test-context-id"> <xsl:apply-templates select="." mode="generate-id" /> </xsl:variable> <xsl:if test="normalize-space($test-context-id) = normalize-space($this-context-id)">match</xsl:if> </xsl:for-each> </xsl:variable> <xsl:if test="not(normalize-space($preceding))"> UNIQUE CONTEXT: <xsl:copy-of select="." /> </xsl:if> </xsl:for-each> </xsl:template> This is really messy and will take a lot of processing power for large source documents, but it seems to work with the example that you gave in SAXON and Xalan-C++. I hope that helps, Jeni Jeni Tennison http://www.jenitennison.com/ XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list
Current Thread |
---|
|
<- Previous | Index | Next -> |
---|---|---|
Re: How to remove duplicates nodes?, Joel Riedesel | Thread | Tools to create HTML documentation , Mike Van Riper |
Re: How to remove duplicates nodes?, Joel Riedesel | Date | RE: Displaying SVG, Chris Bayes |
Month |